Problem with arrays

Started by
6 comments, last by Molle85 12 years, 5 months ago
Hi,

So what I'm trying to make is a clone of Galaxian to learn more C++. The problem is that I'm not quite getting what I want. What I'm trying to do is make only one enemy arc and the others just move. I've been trying several things, but it is either that they all arc, or one keeps on arcing and doesn't fall down, or they all fall down. So if someone could give me some suggestions on how to solve my problem, that would make me one happy person :) Also a strange thing is that my bullet of my enemy does not seem to update. So I guess I have problems passing arrays as parameters and making the right updates.

So what I have done now is that I made an Invader class where I try to handle all the logic movement of the invader so that I can add it in my game.cpp class. I tried to make the functions this way that I can use it on multiple enemies. So i.e. a blue drone, and a yellow drone and a purple drone. Because the original galaxian also had this.

So this is what I did:

Invader.cpp



Invader::Invader()
{
enemyState = MOVING;
enemyBullet = new Bullet();
enemyBullet->isFired = false;
enemyBullet->yPos = 0;
isAlive = true;
countTimer = 10;
countArc = 0;
}

Invader::~Invader()
{}

void Invader::EnemyMovement(Invader invader[], int length)
{
for(int i =0; i< length; i++)
{
switch (enemyState)
{
case MOVING:
{
invader.EnemyMoving(invader, length);
break;
}
case ARCING:
{
invader->EnemyArcing(invader, length);
break;
}
case FALLING:
{
invader->EnemyFalling();
break;
}
case REJOINING:
{
invader->EnemyRejoinging();
break;
}
default:
NONE;

} // switch
}

}

void Invader::EnemyMoving(Invader invader[], int length)
{
//std::cout << "moving"<< std::endl;
for(int i =0; i< length; i++)
{

if(moveLeft)
{
invader.Xpos -= 1;
}
else
{
invader.Xpos += 1;
}

if(invader.countTimer >= 0)
{
invader.countTimer--;
if(invader.countTimer <= 0)
{

invader.countTimer = 0;
enemyState = ARCING;
}

}
}
}

void Invader::EnemyArcing(Invader invader[], int length)
{
std::cout << "arcing"<< std::endl;
for(int i =0; i <length; i++)
{
int radius = 80;

if(invader.countArc == 0)
{

PivotX = invader.Xpos + radius;
PivotY = invader.Ypos;
invader.countArc++;
}

// start arcing
if (countArc != 0)
{
invader.Xpos = PivotX + (radius * cosf(countArc * 2 * PI/360 + PI));
invader.Ypos = PivotY + (radius * sinf(countArc * 2 * PI/360 + PI));
invader.countArc++;
}

// change state
if(invader.countArc == 180)
{
invader.enemyState = FALLING;
invader.countArc = 0; // ready for next time.
}
}
}

void Invader::EnemyFalling()
{
std::cout << "falling"<< std::endl;
countTimer = 10;
Ypos += 1;
UpdateEnemyBullet();
if(Ypos > SCRHEIGHT)
{
enemyState = REJOINING;
}
}

void Invader::EnemyRejoinging()
{
std::cout << "rejoining"<< std::endl;
}

void Invader::ChecksEnemyBorder(Invader invader[], int length)
{
for(int i = 0; i< length; i++)
{
if(invader.isAlive && invader.Xpos > SCRWIDTH - 50)
{
moveLeft = true;
}
else if(invader.isAlive && invader.Xpos < 0)
{
moveLeft = false;
}
}
}

//Updates the bullet movement and sets bullet draw to false if out of screen
void Invader::UpdateEnemyBullet()
{
if(!enemyBullet->isFired && isAlive)
{
enemyBullet->isFired = true;
enemyBullet->xPos = xpos + 16;
enemyBullet->yPos = ypos;
enemyBullet->yPos += 3;

std::cout << "xpos = " << Xpos << "ypos = " << Ypos << std::endl;
std::cout << "enemybullet ypos = " << enemyBullet->yPos << std::endl;

if(enemyBullet->yPos > SCRHEIGHT)
{
enemyBullet->isFired = false;
}
}

}



game.cpp



Invader blueDrones[BLUEDRONES];
bool Invader::moveLeft = false;

void Game::Init()
{
int counter = 0;
for(int j = 0; j< 2; j++)//colum
{
for(int i =0; i < 2; i++)// row
{
blueDrones[counter].Xpos = 100 + ( i * 60);
blueDrones[counter].Ypos = 50 + (j * 50);
blueDrones[counter].Graphic = blueDroneSpr ;
counter++;
}
}

}




void Game::Tick( float a_DT )
{
for(int t = 0; t < BLUEDRONES; t++)
{
blueDrones[t].ChecksEnemyBorder(blueDrones, BLUEDRONES);
blueDrones[t].EnemyMovement(blueDrones, BLUEDRONES);
blueDrones[t].EnemyMoving(blueDrones, BLUEDRONES);

}


Draw();

}




void Game::Draw()
{
//Draw blue drones
int counter = 0;
for(int i = 0; i < BLUEDRONES; i++)// row
{
if(blueDrones.isAlive)
{blueDroneSpr->CopyTo(m_Screen, blueDrones.Xpos, blueDrones.Ypos);}

if(blueDrones.enemyBullet->isFired)
{bulletSpr->CopyTo( m_Screen, blueDrones.enemyBullet->xPos, blueDrones.enemyBullet->yPos);}
counter++;
}
}

Advertisement
Why are you updating all the invaders from within every invader?
Surely each invader should only update themselves

Edit: You aren't deleting the bullet in the destructor either
And how would I make them update only one? Because I was trying to only to update the index of the array, but I think I don't understand the concept very well about how parameterized arrays work. Because now I am updating them all I guess...

Oh thanks for the tip. I will delete the enemy bullet in my destructor. I'm still learning the concept about destructors and deleting objects. Because I first learned some C# and XNA before I now started with C++, so I'm used to the garbage collector.

You are updating all of them n^2,
first you are looping through all of them in Game::Tick() and then you loop through all of them again in all the methods.

Remove all the loops in all Invader methods!
And don't send the array as a parameter unless you want a certain Invader to be aware of the others whilst performing an action.
Oh I thought I needed to loop through them in the Invader class so that the function in the Game class would have the correct index of the array, so of only one invader.

Oke I have deleted all the for loops in my Invader class, but now they are all arcing again and not just one. I guess I'm still doing something wrong. Because I want them all to move but only one to arc.
So I have the conflict that only one invader should be aware of doing something "arcing, falling, rejoining" while the others keep doing their business by just moving left and right. So how could I achieve that?

You are calling EnemyMoving() twice aswell, once in Game::Tick() and once in Invader::EnemyMovement()

Arcing, they are all just synchronized, try setting this in the constructor
countTimer = rand() % 100;

Edit:
Or you could in GameTick pick one that should arc.
[source]
if( rand() % 10 == 0 )
blueDrones[ rand() % BLUEDRONES ].SetState( ARCING );
[/source]
[source='l'][/source][type]l[/type]Oh thats why they all arc at the same time. But if I would put countTimer = rand() % 100; in my Invader constructor, they would not start arcing at the same time, but still very close to each other.

So you recomend me to make a function that sets the state of my enemy? Something like?:

[source]
void SetState(EnemyState enemyState);
[/source]



It is up to you and your design whether the Game should decide who and when to arc, or if they should decide it themselves.
But yes, i would recommend it.

This topic is closed to new replies.

Advertisement