Public Group

# Problem with arrays

This topic is 2391 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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::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++; } } 

##### Share on other sites
Surely each invader should only update themselves

Edit: You aren't deleting the bullet in the destructor either

##### Share on other sites
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.

##### Share on other sites
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.

##### Share on other sites
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?

##### Share on other sites
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]

##### Share on other sites
[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]

##### Share on other sites
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.

• 9
• 13
• 41
• 15
• 14