Jump to content
  • Advertisement
Sign in to follow this  
v.mommersteeg

Problem with arrays

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

If you intended to correct an error in the post then please contact us.

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!