Multiple animation at a time - c++

I'm making a Asteroids game but I can not get to play more than one explosion at a time. Just get to do one at a time ...
This is my code I call in the main loop:
for(i = 0; i < MAX_SHOTS; i++) {
for(j = 0; j < MAX_ASTEROIDS; j++) {
if(shot[i].CheckCollision(asteroide[j])) {
shot[i].SetPos(-100, 0);
explosionSnd.Play();
numAst = j;
explosion[numExp++].Enable(true);
if(numExp == MAX_EXPLOSIONS-1) {
numExp = 1;
}
}
}
}
for(i = 1; i < MAX_EXPLOSIONS; i++) {
if(explosion[i].Enable()) {
explosion[i].SetPos(asteroide[numAst].GetX(), asteroide[numAst].GetY());
explosion[i].Draw();
if(explosion[i].GetFrame() == 5) {
explosion[i].Enable(false);
}
}
}
If I shot to an asteroid and after I shot to another, the animation is cut and goes to the new asteroid.
Any help?
Thank you.

Inside your second loop, you're moving each explosion to the location of the asteroid asteroide[numAst] - you're playing all the explosions, just all at the same place!
You should only position the explosion once after you Enable(true) it, when it's created in the first loop, not each time you draw it.
Hope that helps.

Related

sfml/c++ - Using Vector for Multiple Enemy Class

I'm trying game development. I tried a sample from a tutorial site like this:
int number = 10;
std::vector<std::unique_ptr<enemy> > enemies1;
for (unsigned i = 0; i < number; ++i) {
enemies1.emplace_back(std::unique_ptr<enemy>(new enemy(sf::Vector2f(100 * i + 1500, 1000), sf::Vector2f(15, 10), sf::Color(255, 255, 255, 0))));
}
//update
for (unsigned i = 0; i < number; ++i) {
enemies1[i]->update();
}
//render
for (unsigned i = 0; i < number; ++i) {
window.draw(enemies1[i]->enemysprite);
}
I'm using vector for creating multi enemies from my enemy class. Everything is ok I can draw 10 enemies on screen and they are moving and such. But if I try to delete an enemy like this:
if (!enemies1.empty())
{
for (unsigned i = 0; i < number; ++i) {
if (enemies1[i]->rect.getGlobalBounds().intersects(sprite.getGlobalBounds()))
enemies1.erase(enemies1.begin() + 1);
}
}
when the program starts a collision occurs everything is stopping. My question is what's the best way to create multiple enemies because I need to spawn and delete them in my game and I'm still learning.
I don't know whether my implementation correct or not. I wonder what should I do? In this code, I can't erase enemies from this vector.
I appreciate every piece of advice.
This loop:
for (unsigned i = 0; i < number; ++i) {
if (enemies1[i]->rect.getGlobalBounds().intersects(sprite.getGlobalBounds()))
enemies1.erase(enemies1.begin() + 1);
}
is flawed, because when you call erase, all the subsequent array entries move down 1, so next time round the loop you access the wrong element. Also, you run off the end of the array.
Instead, you can use the erase / remove idiom:
enemies.erase (std::remove_if (enemies.begin(), enemies.end(),
[sprite] (const std::unique_ptr <enemy> &e)
{ return e->rect.getGlobalBounds().intersects(sprite.getGlobalBounds()); }, enemies.end());
My enemy class is this like on shared picture

Tetris shifting 2D array

I'm currently writing a tetris in C++ and I am at the last stage, I need to delete a row when it is full. Once a piece falls it is stored in a boolean array grid[20][10]. For example I check which row is full (or true), if it is I call a method deleteRow, where n is a number of row:
void Grid::deleteRow(int n)
{
for (j = 0; j < WIDTH; j++)
{
grid[n][j] = false;
}
}
Once the row is deleted I call a method moveRowDown:
void Grid::moveRowDown()
{
for (i = 0; i < HEIGHT; i++)
{
for (j = 0; j < WIDTH; j++)
{
grid[i+1][j]=grid[i][j];
}
}
}
So this method does not work, and all of the pieces disappear. I know I am missing the logic. Thanks for the help in advance!
They disappear because you copy 1st empty row to 2nd, then to 3rd and etc.
You need to rewrite your first loop in Grid::moveRowDown() to work from the bottom of a glass:
for (i = HEIGHT-2; i>=0; i--)

Extra sprite spawning when the enemies are redrawn SFML

I am making a game in sfml and at the moment when all of the enemies die. They are set to respawn however when this is happening they are respawning with one extra sprite than before.
The code for loading in the sprites is
unsigned int orcNumber = 5;
for (int i = 0; i < orcNumber; i++)
{
SpriteVector.push_back(ogreSprite);
SpriteVector[i].setPosition(spawnPointX[i], spawnPointY[i]);
}
The code for removing the enemies if they are offscreen or shot is similar to below using erase.
for (unsigned j = 0; j < SpriteVector.size(); j++)
{
if (this->SpriteVector[j].getPosition().x < 0 - 80 )
{
//this succesfully removes the object from the vector
SpriteVector.erase(SpriteVector.begin() + j);
std::cout << "Container size..." << SpriteVector.size() << "\n";
}
}
The statement for redrawing them is:
unsigned int orcNumberRespawn = 5;
if (SpriteVector.size() <= 1)
{
for (int i = 0; i < orcNumberRespawn; i++)
{
SpriteVector.push_back(ogreSprite);
SpriteVector[i].setPosition(spawnPointX[i], spawnPointY[i]);
}
}
window.draw(SpriteVector[i]);
Can anyone identify why when the sprites need to be redrawn it draws with + 1 sprite everytime?
The issue was with a loop outside of these vector loops.

C++ Tetris: A function that deletes lines

I've been studying this tetris tutorial and I've come across the function that deletes lines and brings the row/s down one level. I'm kind of understanding what is going on with these functions, but some parts are confusing me. I'll try and explain it best I can, but here is the link to the lesson if you need it: http://javilop.com/gamedev/tetris-tutorial-in-c-platform-independent-focused-in-game-logic-for-beginners/
This, to me, looks like a function to get the array to start at the last number of a line:
void Board::DeleteLine (int pY)
{
// Moves all the upper lines one row down
for (int j = pY; j > 0; j--)
{
for (int i = 0; i < BOARD_WIDTH; i++)
{
mBoard[i][j] = mBoard[i][j-1];
}
}
}
Then, there is the function that is causing me problems, which I will explain:
void Board::DeletePossibleLines ()
{
for (int j = 0; j < 20; j++)
{
int i = 0;
while (i < 10)
{
if (mBoard[i][j] != 1) break;
i++;
}
if (i == 10) DeleteLine (j);
}
}
In case you're not familiar, the idea here is to delete a row that consists entirely of 1. But if (mBoard[i][j] != 1) break; would stop the loop if the first line wasn't 1. How would the loop reach a 1 that is somewhere in the middle of the mBoard[][] array if break stops it from doing anything possible straight away?
Am I missing something here? This is my interpretation of it. Perhaps somebody sees something I do't?
Edit:
Thanks for the replies, appreciated.
You could structure the code like this aswell:
for (int j = 0; j < 20; j++)
{
int i = 0;
while (i < 10)
{
if (mBoard[i][j] != 1)
{
break; //only breaks the while loop and will continue with if (i == 10)
}
else
{
i++;
}
}
if (i == 10)
{
DeleteLine (j);
}
}
Now you can clearly see, that the break; is only interrupting your while loop but not your for loop.
The break will jump out of the while loop. So if you encounter a line which has a non-1 somewhere in the middle, i will be the index in the line, and the for loop will continue with the next line (j), starting with i=0 again.
break only interrupts one loop, the while loop in your case. The for loop continues happily.
On a side note, this while could easily (and should) be refactored into a for, and can be compacted according to its recognizable for-if-break pattern :
for (int j = 0; j < 20; ++j)
{
int i;
for(i = 0; i < 10 && mBoard[i][j] == 1; ++i);
if (i == 10) DeleteLine (j);
}

Access violation writing location 0x00000000. C++ / SFML game

I'm working on a school project using C++ and SFML 2.0, it's due for Tuesday and I've just recently run in to this problem.
I've put an arrow on where the latest Call Stack is.
These are the code parts that I suspect might have something wrong in them. I'm also very new to c++ and I know I do alot of things wrong.
This is in my Background class, it loads all my tiles, sets their position and tiletype and so on.
The GetWayPointList returns a vector of tiles to my EnemyManager class
void Background::Load(QuadTree * quadTree) {
int tempTiles[32][32] = {... Lots of 1's and 0's in here };
for(int i = 0; i < 32; i++)
{
for(int j = 0; j < 32; j++)
{
---> tile[j][i]->tileType = tempTiles[j][i];
tile[j][i]->setPosition(sf::Vector2f((float)(i*32),(float)(j*32)));
if(tile[j][i]->tileType == 1)
{
quadTree->AddObject(tile[j][i]);
}
else if(tile[j][i]->tileType == 0)
{
tile[j][i]->distanceFromStart = INT_MAX;
tile[j][i]->parent = NULL;
vector<Tile*> tempTiles;
if(tile[j+1][i]->tileType == 0)
tempTiles.push_back(tile[j+1][i]);
if(tile[j-1][i]->tileType == 0)
tempTiles.push_back(tile[j-1][i]);
if(tile[j][i+1]->tileType == 0)
tempTiles.push_back(tile[j][i+1]);
if(tile[j][i-1]->tileType == 0)
tempTiles.push_back(tile[j][i-1]);
tile[j][i]->setSuccessors(tempTiles);
tilesList->push_back(tile[j][i]);
}
}
}
}
vector<Tile*>* Background::GetWayPointList()
{
return tilesList;
}
The Call Stack itself says TileShooter v0.1.exe!Background::Load(QuadTree*quadTree) Line 68 + 0x2e bytes.
Line 68 is where the arrow is.
If you need more code / info just say.
Any points on what's possibly wrong would be greatly appriciated.
Best Regards, Fredrik W
Edit
I've edited the code some including tile[j][i] = new Tile();
void Background::Load(QuadTree * quadTree) {
int tempTiles[32][32] = {... Lots of 1's and 0's in here };
for(int i = 0; i < 32; i++)
{
for(int j = 0; j < 32; j++)
{
tile[j][i] = new Tile();
tile[j][i]->tileType = tempTiles[j][i];
tile[j][i]->setPosition(sf::Vector2f((float)(i*32),(float)(j*32)));
if(tile[j][i]->tileType == 1)
{
quadTree->AddObject(tile[j][i]);
}
else if(tile[j][i]->tileType == 0)
{
tile[j][i]->distanceFromStart = INT_MAX;
tile[j][i]->parent = NULL;
vector<Tile*> tempTiles;
----> if(tile[j+1][i]->tileType == 0)
tempTiles.push_back(tile[j+1][i]);
if(tile[j-1][i]->tileType == 0)
tempTiles.push_back(tile[j-1][i]);
if(tile[j][i+1]->tileType == 0)
tempTiles.push_back(tile[j][i+1]);
if(tile[j][i-1]->tileType == 0)
tempTiles.push_back(tile[j][i-1]);
tile[j][i]->setSuccessors(tempTiles);
tilesList->push_back(tile[j][i]);
}
}
}
}
vector<Tile*>* Background::GetWayPointList()
{
return tilesList;
}
That didn't really solve but rather moved the error downwards, I've moved my arrow on where the Call Stack has it's latest call.
So your tile member is defined as Tile* tile[32][32]. That's a 2D array of size 32x32 where each element is a pointer to Tile. However, they are just pointers and currently don't point anywhere in particular - accessing them is undefined behaviour (in your case, an access violation). You need to allocate the actual Tile objects:
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 32; j++) {
tile[i][j] = new Tile();
}
}
Don't forget to do the same kind of loop in the destructor of Background that instead does delete tile[i][j];.
Better yet, don't dynamically allocate your tiles and just define tile as:
Tile tile[32][32];
Even better yet (!), use std::array<std::array<Tile,32>,32>. :)
To answer your edit, even though it's invalidated my above answer: You're accessing the j+1th element of tile. When j is 31, you're accessing tile[32] which is outside the bounds of your array.