QMovie. How to set loop count? - c++

I'm using QMovie and gif to create explosion after collision. The problem is that my gif is looping over and over, I've checked loopcount status and it returns -1 (infinite). How to display my gif just one time?
#include "Bullet.h"
#include <QTimer>
#include <QGraphicsScene>
#include <QList>
#include "Enemy.h"
#include "Game.h"
#include <typeinfo>
#include "levels.h"
extern Game * game; // there is an external global object called game
int Bullet::killed = 0;
int Bullet::missed = 0;
double Bullet::accurancy = 0;
Bullet::Bullet(QGraphicsItem *parent): QGraphicsPixmapItem(parent){
// draw graphics
setPixmap(QPixmap(":/images/res/images/bullets/bullet.png"));
missed++; // increse missed when bullet is created
movie = new QMovie(":/images/res/images/effects/explosion/64x48.gif");
processLabel = new QLabel;
processLabel->setMovie(movie);
// make/connect a timer to move() the bullet every so often
QTimer * timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(move()));
// start the timer
timer->start(2);
}
void Bullet::move(){
// get a list of all the items currently colliding with this bullet
QList<QGraphicsItem *> colliding_items = collidingItems();
// if one of the colliding items is an Enemy, destroy both the bullet and the enemy
for (int i = 0, n = colliding_items.size(); i < n; ++i){
if (typeid(*(colliding_items[i])) == typeid(Enemy)){
// increase the score
game->score->increase();
//play explosion animation
movie->start();
movie->setSpeed(180);
processLabel->setAttribute(Qt::WA_NoSystemBackground);
processLabel->setGeometry(QRect(x()-15,y()-15,64,48));
scene()->addWidget(processLabel);
qDebug() << movie->loopCount();
//connect(movie,SIGNAL(finished()),movie,SLOT(stop()));
// remove them from the scene (still on the heap)
scene()->removeItem(colliding_items[i]);
scene()->removeItem(this);
// delete them from the heap to save memory
delete colliding_items[i];
delete this;
killed++;
missed--; // decrese missed if bullet colide with enemy
if((killed+1) % 9 == 0)
{
game->level->Levels::incrementLevels();
game->score->Score::addToSum(); /// TODO
}
//qDebug() << "Already killed: " << killed;
//qDebug() << "Already missed: " << missed;
// return (all code below refers to a non existint bullet)
return;
}
}
// if there was no collision with an Enemy, move the bullet forward
setPos(x(),y()-1);
// if the bullet is off the screen, destroy it
if (pos().y() < 0){
scene()->removeItem(this);
delete this;
}
}

I had the same question and didn't find anything, so here's my solution:
connect the signal "frameChanged(int)" to:
void Bullet::frameChanged_Handler(int frameNumber) {
if(frameNumber == (movie->frameCount()-1)) {
movie->stop();
}
}
If you want to run X times the loop you just have to add a static counter to know how many times you've passed the last frame:
void Bullet::frameChanged_Handler(int frameNumber) {
static int loopCount = 0;
if(frameNumber == (movie->frameCount()-1)) {
loopCount++;
if(loopCount >= MAX_LOOP_TIMES)
movie->stop();
}
}
and of course, connect with this:
connect(movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged_Handler(int)));
That's it... Hope it can help you.

Related

How to reset number of instances of a class to 1 on every loop iteration?

I have a player class where I am storing the player's current position, the number of players in the game and a static variable to store the total number of players like so:
#ifndef PLAYER_H
#define PLAYER_H
#include <ctime>
#include <random>
#include <iostream>
using std::time;
using std::cout;
class Player
{
private:
int m_Player_currentPosition, m_Player_number;
static int m_Player_numberOfPlayers;
public:
Player::Player():m_Player_currentPosition(1) {
m_Player_number = m_Player_numberOfPlayers;
++m_Player_numberOfPlayers;
}
void m_Player_SetPosition();
int m_Player_GetPosition();
int m_Player_GetPlayerNumber() { return m_Player_number; }
void m_Player_SetNumberOfPlayers() { m_Player_numberOfPlayers = 1; }
~Player() { --m_Player_numberOfPlayers; }
};
int Player::m_Player_numberOfPlayers = 1;
#endif
I also have a game class that creates a certain number of player instances using a vector. In my game class, the plan is to create players depending on user input (between 2-4 number of players) using m_Game_SetPlayers() member function and also printing the details of the players using the m_Game_PrintPlayers() member function.
#ifndef GAME_H
#define GAME_H
#include <iostream>
#include "Board.h"
#include "Player.h"
using std::cout;
using std::cin;
using std::vector;
class Game {
private:
bool m_Game_quit;
int m_Game_choice;
Board board;
vector<Player> m_Game_players;
public:
Game();
const bool &m_Game_GetQuit() const;
void m_Game_SetPlayers()
{
int numberOfPlayers = 2;
cout << "How many players (2-4)? ";
cin >> numberOfPlayers;
if (numberOfPlayers < 2 || numberOfPlayers > 4) {
numberOfPlayers = 2;
}
m_Game_players.resize(numberOfPlayers);
}
void m_Game_PrintMenu();
void m_Game_PrintInstructions();
void m_Game_GetChoice();
void m_Game_PrintPlayers()
{
cout << '\n';
vector<Player>::iterator iter;
for (iter = m_Game_players.begin(); iter != m_Game_players.end(); ++ iter) {
cout << "Player " << iter->m_Player_GetPlayerNumber() << "'s position: " << iter-
>m_Player_GetPosition() << '\n';
}
}
void Update();
};
#endif // !GAME_H
However, in my main class, I am calling the Game class's update function under a while loop. Here is my game update member function declared in a separate implementation file that decides the control flow of the game.
void Game::Update()
{
m_Game_GetChoice();
switch (m_Game_choice) {
case 0: cout << "---Bye---\n";
m_Game_quit = true;
break;
case 1:
system("cls");
m_Game_PrintInstructions();
break;
case 2:
system("cls");
m_Game_SetPlayers();
system("cls");
board.m_Board_PrintBoard();
m_Game_PrintPlayers();
m_Game_players[0].m_Player_SetNumberOfPlayers();
break;
default:
cout << "--Invalid Option---\n";
break;
}
}
Here is my while loop in the main function:
#include "Game.h"
int main() {
Game game;
while (!game.m_Game_GetQuit()) {
system("cls");
game.m_Game_PrintMenu();
game.Update();
system("pause");
}
}
When I ran this program the first time, it worked as expected. However, imagine if I choose the play option from the menu and I enter 2 players, it creates 2 instances of the player class. On the next while loop iteration, I increase the size to 4 players which also works perfectly sometimes. Then, when I reduce the size and then again increase the size, the player number does not match. Here are the following images to help understand the problem:
Input 1: https://i.stack.imgur.com/reHjE.png
Output 1: https://i.stack.imgur.com/Dt68V.png
Input 2: https://i.stack.imgur.com/Xo83c.png
Output 2: https://i.stack.imgur.com/2Qso6.png
The expected output is:
Player's position 1: 1
Player's position 2: 1
Player's position 3: 1
So, I thought that I need to delete my instances, but since I cannot delete instances on a stack memory as long as I am in a while loop (How do I manually delete an instance of a class?, http://www.cplusplus.com/forum/beginner/107822/). I thought that I will resize the vector. It did resize the vector, but then it does not delete the instances of the player class but instead created a new instance of that class. Is there a way to destroy all the instances of the class on a stack memory even when it is inside the scope? If not, how do I solve this problem?
I may/may not have provided the code needed to debug this problem. So, I have attached my entire code on https://github.com/F3INTH34RTED/Cpp/tree/master/Beginner/16SnakesAndLadder if need be.
When you increase the size of the vector, say from 2 to 3, it only needs to create one new instance of Player, so it will create a single player with the next number.
The line
m_Game_players[0].m_Player_SetNumberOfPlayers();
on the previous loop iteration sets the global counter to 1. So this single new player gets number 1, not number 3 like you expect. You should be able to remove the above line and things will work as expected.
On a design note, it would probably be wiser to recreate the vector entirely when the number of players is changed and explicitly give each player a number via the constructor, like this:
void m_Game_SetPlayers()
{
int numberOfPlayers = 2;
cout << "How many players (2-4)? ";
cin >> numberOfPlayers;
if (numberOfPlayers < 2 || numberOfPlayers > 4) {
numberOfPlayers = 2;
}
m_Game_players.clear();
for (int i = 1; i < numberOfPlayers; i++) {
m_Game_players.push_back(Player(i));
}
}
Updating the Player constructor to match, of course.
Your issue is that std::vector::push_back will do copy/move when it needs to resize internal buffer, and your (auto generated default) copy/move constructors doesn't handle that, you might do for example:
class Player
{
private:
int m_currentPosition;
std::optional<int> m_number;
static int m_numberOfPlayers;
public:
Player() : m_currentPosition(1), m_number(++m_numberOfPlayer) {}
Player(const Player&) = delete;
Player(Player&& rhs) : m_currentPosition(rhs.m_currentPosition), m_number(rhs.m_number) { rhs.m_number = std::nullopt; }
Player& operator = (const Player&) = delete;
Player& operator = (Player&& rhs) { std::swap(m_currentPosition, rhs.m_currentPosition); std::swap(m_number, rhs.m_number); }
int GetPlayerNumber() const { return *m_number; }
~Player() { if (m_number) --m_numberOfPlayers; }
};

QGraphicsScene crashes after even the tiniest update

I'm working currently on simple project in Qt. It is based on popular game "Ludo". But I've got annoying problem with making any changes on screen. Board drawing works nice, but it's enough to uncomment line with play() function and disaster guaranteed. Simply I'm not able to setPixmap of field in Player::turn() to show pawns' movement. Scene becomes plain and every drawn field disappears. On the other hand, game runs logically and correctly due to output. Unfortunately, it completely doesn't cooperate with GUI.
I attached images "before-after" and necessary code.
main.cpp
QApplication a(argc, argv);
Board *scene = new Board();
QGraphicsView *view = new QGraphicsView(scene);
view->resize(1200, 1000);
view->show();
scene->draw();
// scene->play();
return a.exec();
Board::play()
dice = new Dice();
unsigned int i=0;
while(true) {
bool playMore = players.at(i)->turn(dice, players, fieldsToPlay);
if(playMore) {
i++;
if(i == 4)
i=0;
}
else break;
}
Player::turn()
int result;
std::cout << "Player " << colour << " ";
if(hasPawnOnField) {
// TODO: check if field has pawn
result = dice->roll();
std::cout << result << '\n';
while(result) {
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/border.png"));
pawns.at(0)->currentField->setPawn(nullptr);
bool finito = pawns.at(0)->move(fieldsToPlay, baseAndFinish);
pawns.at(0)->currentField->setPawn(pawns.at(0));
char col = pawns.at(0)->getColour();
switch (col) {
case 'b':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/bluepawn.png"));
break;
case 'r':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/redpawn.png"));
break;
case 'y':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/yellowpawn.png"));
break;
case 'g':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/greenpawn.png"));
break;
}
if(finito) {
finishedPawns++;
delete pawns.at(0);
pawns.erase(pawns.begin());
hasPawnOnField = false;
break;
}
result--;
}
if(finishedPawns == 4) // condition which ends the game
return 0;
}
else {
int attempts = 3;
while(attempts) {
result = dice->roll();
std::cout << result << '\n';
if(result == 6) {
hasPawnOnField = true;
if(start->getPawn()) {
char col = start->getPawn()->getColour();
switch (col) {
case 'b':
players.at(0)->pawns.at(0)->setField(fieldsToPlay.at(0));
players.at(0)->pawns.at(0)->zero();
fieldsToPlay.at(0)->setPawn(players.at(0)->pawns.at(0));
fieldsToPlay.at(0)->set_Pixmap(QPixmap(":/img/bluepawn.png"));
break;
case 'r':
players.at(1)->pawns.at(0)->setField(fieldsToPlay.at(12));
players.at(1)->pawns.at(0)->zero();
fieldsToPlay.at(12)->setPawn(players.at(1)->pawns.at(0));
fieldsToPlay.at(12)->set_Pixmap(QPixmap(":/img/redpawn.png"));
break;
case 'y':
players.at(2)->pawns.at(0)->setField(fieldsToPlay.at(24));
players.at(2)->pawns.at(0)->zero();
fieldsToPlay.at(24)->setPawn(players.at(2)->pawns.at(0));
fieldsToPlay.at(24)->set_Pixmap(QPixmap(":/img/yellowpawn.png"));
break;
case 'g':
players.at(3)->pawns.at(0)->setField(fieldsToPlay.at(36));
players.at(3)->pawns.at(0)->zero();
fieldsToPlay.at(36)->setPawn(players.at(3)->pawns.at(0));
fieldsToPlay.at(36)->set_Pixmap(QPixmap(":/img/greenpawn.png"));
break;
}
}
pawns.at(0)->setField(start);
start->setPawn(pawns.at(0));
start->set_Pixmap(baseAndFinish.at(finishedPawns)->getPixmap());
baseAndFinish.at(finishedPawns)->set_Pixmap(QPixmap(":/img/border.png"));
break;
}
attempts--;
}
}
Pawn::move()
passedFields++;
if(passedFields >= 48) {
currentField = basFin.at(4+(passedFields-48));
if(passedFields == FINISH) {
FINISH--;
delete basFin.at(basFin.size()-1);
basFin.pop_back();
return true;
}
}
else
currentField = fieldsToPlay.at( (startID+passedFields)%48);
return false;
Board.h
class Board : public QGraphicsScene {
Q_OBJECT
public:
Board();
virtual ~Board();
void draw();
void drawField(std::vector<Field *> &vec, Vector &current, Vector dir, QString image);
void play();
static const int rect_size = 70;
Vector directions[4] = {Vector (0, -rect_size), //up
Vector (rect_size, 0), //right
Vector (0, rect_size), //down
Vector (-rect_size, 0) }; //left
private:
std::vector<Field *> fieldsToPlay;
std::vector<Player *> players;
std::vector<Field *> fieldsBlue; //fields 0-3 basement, fields 4-7 finish
std::vector<Field *> fieldsRed;
std::vector<Field *> fieldsYellow;
std::vector<Field *> fieldsGreen;
Dice *dice;
QTimer *timer;
};
Scene before updating Pixmap
Scene after
What am I doing wrong? How to update my scene in runtime without crash?
Rather than use an infinite loop you could make use of a QTimer (I see Board already has a QTimer * member so perhaps that was the intention all along). Rather than use an explicit timer you might want to use QTimer::singleShot to `nudge' the game one step forward at a time.
Firstly, make the player counter/index i a member of Board and initialise it and dice in the constructor...
Board::Board ()
: dice(new Dice)
, i(0)
{
...
}
Now change Board::play so that it makes a single call to Player::turn for the current player and rearms a timer if required...
void Board::play ()
{
/*
* Give the current player their turn.
*/
bool playMore = players.at(i)->turn(dice, players, fieldsToPlay);
if (playMore) {
/*
* The game hasn't yet finished so update the player index
* and rearm the timer with a lambda to make another call
* to play() in 1 second.
*/
i++;
if (i == 4)
i=0;
QTimer::singleShot(1000,
[this]()
{
play();
});
}
}
I haven't tested the above but it at least shows the basic outline of what you should aim for.

Terminate called after throwing an instance of 'std::bad_alloc' while using standard vector functions

I'm working on an assignment which asks us to model an 'elimination voting' procedure for a reality game. For that we use one class (Vote) for recording the name of the player to be eliminated and another (Voting) which doesn't get instanced anywhere, because its members are static (we need them to be). The votes are stored on a vector inside the Voting class.
The problem is that even when I use the push_back function to store the votes in the vector, after running the program for a few times I get an std::length_error with what(): basic_string::_M_create. After I close it and rerun, the first time I get an error like the one on the title (std::bad_alloc).
Any ideas? I'm suspecting that it has to do with the vector not deallocating memory correctly, but I'm not sure.
My code (Voting.h):
#ifndef VOTING_H_INCLUDED
#define VOTING_H_INCLUDED
#include <vector>
#include <map>
#include "Vote.h" //ignore this one
#include "Team.h" //this one too
class Voting
{
public:
static vector <Vote> votes; //votes cast during voting procedure
static map <string, int> results; //voting results (key: name, value: number of votes)
static void votingProcess(Team &team); //the whole voting procedure
};
#endif // VOTING_H_INCLUDED
Voting.cpp:
#include <vector>
#include <map>
#include <cstdlib>
#include "Vote.h"
#include "Voting.h"
using namespace std;
vector <Vote> Voting::votes(1); //initialize the vector for the votes
void voteCast(Team &team);
void Voting::votingProcess(Team &team)
{
voteCast(team);
}
void voteCast(Team &team)
{
int playerNumber = team.getNumberOfPlayers(); //number of players right now still in the team
int votingPlayer = 0; //index of the currently voting player
int votedPlayerIndex = -1; //index of the player to be voted for elimination
int reasonIndex = -1; //index of the selected reason for voting
Vote draft; //temporary empty vote
srand(time(NULL)); // initialize the RNG
Voting::votes.clear(); //clear the vector of any past votes
string reasons[4] = {"Den ta pame kala metaxi mas", "Einai ikanoteros/i apo emena kai ton/ti theoro apeili", "Den exei na prosferei kati stin omada", "Prospathei sinexeia na sampotarei tis prospatheies mas"};
//some reasons for elimination (i've tried smaller strings and even chars and it didn't work, so don't bother)
do
{
if (team.getPlayers()[votingPlayer].getAge() != 0 && team.getPlayers()[votingPlayer].getVotes() > 0)
//if the player with index votingPlayer has not been eliminated and has still votes to cast
{
do
{
votedPlayerIndex = rand() % 11; //select a random player for elimination
reasonIndex = rand() % 5; //select a random reason for it
}
while ((team.getPlayers()[votedPlayerIndex].getAge() == 0) || (votedPlayerIndex == votingPlayer) || (team.getPlayers()[votedPlayerIndex].getImmunity() == true));
// selection continues if the selected player has already been eliminated,
//if the selected player is the same as the voting player or if the selected player has immunity from elimination
team.getPlayers()[votingPlayer].setVotes(team.getPlayers()[votingPlayer].getVotes() - 1); //reduce the player's available votes by 1
draft.setVotedPlayer(team.getPlayers()[votedPlayerIndex].getName()); //write the name of the player to be voted in an empty Vote object
draft.setReason(reasons[reasonIndex]); //and the reason too
Voting::votes.push_back(draft); //push the Vote obj. in the vector
}
else
{
votingPlayer++; //ignore and get to the next player
}
}
while (votingPlayer < playerNumber); //vote casting continues until every player has casted a vote
}
Vote.h:
#ifndef VOTE_H_INCLUDED
#define VOTE_H_INCLUDED
#include <string>
#include <iostream>
using namespace std;
class Vote
{
string voted; //name of the player to be eliminated
string reason; //reason for elimination
public:
Vote() { voted = ""; reason = ""; } //constructor without parameters
Vote(string player, string reason) { voted = player; this -> reason = reason;} //constructor with parameters (this one is used)
~Vote() { cout << "Vote object destroyed" << endl; }; //destructor
string getVotedPlayer() { return voted; } //getters
string getReason() { return reason; }
void setVotedPlayer(string player) { voted = player; } //setters
void setReason(string reason) { this -> reason = reason; }
void status() { cout << "Voted player: " << voted << endl << "Reason: " << reason << endl;} //status function
};
#endif // VOTE_H_INCLUDED
The reason is that you have an array with 4 elements (so only indices 0..3 are valid) and you are allowing yourself to index it with the 5 possible values (0..4), where 4 is not a valid index.
Here is the definition of the array:
string reasons[4] = {"Den ta pame kala metaxi mas", "Einai ikanoteros/i apo emena kai ton/ti theoro apeili", "Den exei na prosferei kati stin omada", "Prospathei sinexeia na sampotarei tis prospatheies mas"};
Here is the selection of the index:
reasonIndex = rand() % 5;
Here is the use of that index:
draft.setReason(reasons[reasonIndex]);
That is why you are seeing an error from basic_string::_M_create because you are copying from a value that you have no idea is actually a string.
In the line that sets reasonIndex just change the 5 to a 4.

Error C2280. Attempting to reference a deleted function. Getting this error when trying to delete an enemy and laser from their data structures

I am building my first game in C++/SDL in OOP and have come across an issue that I didn't have in my singular file version of the game.
When checking for collisions, if a collision has been detected, I am wanting the players laser and enemy ship to be destroyed from my data structure but I am getting an error that I am unable to resolve.
Error C2280. Attempting to reference a deleted function.
Without posting too much code and trying to make it easier for you to read I have included what I think is necessary.
'CheckCollisions' is being called from the function that has the data structure holding both enemies and lasers.
Thank you.
game.cpp
void Game::start(Display& display, Media& media, Player& player)
{
//Initialize SDL
if (!display.init())
{
printf("Failed to initailize.", SDL_GetError());
}
else
{
//Load all media
if (!media.load(display))
{
printf("Failed to load media", SDL_GetError());
}
else
{
SDL_Event e;
std::vector<Enemy> enemies; //Holds all enemies
std::vector<Laser> playerLasers; //Holds all of player lasers
//std::vector<Laser> enemyLasers; //Holds all of the enemy lasers
addEnemy(enemies); //Adds enemies to the game
//Begin game loop
while (!m_quit)
{
//Event management
while (SDL_PollEvent(&e) != 0)
{
if(e.type == SDL_KEYDOWN)
{
player.movement(e);
}
if (e.type == SDL_MOUSEBUTTONDOWN)
{
player.shoot(playerLasers);
}
}
//Movement
player.movementBounds();
moveLasers(playerLasers);
moveEnemies(enemies);
//Collision detection
checkCollisions(player, enemies, playerLasers);
//Render
display.render(media, player, enemies, playerLasers);
//Simulate 60 fps - Read on tutorial, not entirely sure if this is ok.
SDL_Delay(16);
}
}
}
}
bool Game::checkCollisions(Player& player, std::vector<Enemy>& enemies, std::vector<Laser>& playerLasers, int& enemyPos)
{
//Check for playerLaser/Enemy collision
for (int playerLaser = 0; playerLaser < playerLasers.size(); playerLaser++)
{
for (int enemy = 0; enemy < enemies.size(); enemy++)
{
//If collision has been detected, delete both playerLaser and Enemy
if (findPlayerLaserCollision(playerLasers[playerLaser], enemies[enemy]))
{
printf("Collision");
playerLasers.erase(playerLasers.begin() + playerLaser);
enemies.erase(enemies.begin() + enemy);
}
}
}
}
Enemy.h
#pragma once
#include <SDL.h>
#include "MoveDirection.h"
struct Enemy
{
Enemy(SDL_Rect pos, int movementSpeed, MoveDirection dir)
{
m_pos = pos;
m_movementSpeed = movementSpeed;
m_dir = dir;
}
SDL_Rect m_pos; //Position of enemy
int m_movementSpeed = 0; //Movement speed of enemy
MoveDirection m_dir; //Movement direction of enemy
const int MIN_X_POS = 0;
const int MAX_X_POS = 750;
};
Laser.h
#pragma once
#include <SDL.h>
#include "MoveDirection.h"
struct Laser
{
Laser(SDL_Rect pos, int movementSpeed, MoveDirection dir)
{
m_pos = pos;
m_movementSpeed = movementSpeed;
m_dir = dir;
}
SDL_Rect m_pos; //Position of enemy
int m_movementSpeed = 0; //Movement speed of enemy
MoveDirection m_dir; //Movement direction of enemy
};
The Enemy class has two const members, so assignment operator can't be generated for this class by the compiler and is defined as deleted (hence the "deleted function" error happens).
You start your loop with for (int enemy = 0; enemy < enemies.size(); enemy++) but inside the loop you call enemies.erase(enemies.begin() + enemy); which means that the loop index is now invalid. You started with a vector of size enemies.size() but you resized it by calling erase in your loop

Unhandled exception when using difftime()

I am creating a program that reads in data about fireworks from an XML file (such as type, colour, time in milliseconds it launches and how long it lasts for etc). This then displays the fireworks display using openGL in a loop.
My approach to this is to have a manager class, that takes in a vector of the xml read fireworks and moves them between 3 different vectors: inactiveFireworks (those that are yet to fire), activeFireworks (those that need to be animated) and depletedFireworks (those that will be pushed back to inactiveFireworks when the display is run).
To check to see if a firework needs to be fired, I need to work out the difference between the time the firework manager was called and the current time of the program and multiply that by 1000 to get milliseconds.
eg: if a firework is due to fire at 3000, it will be called 3 seconds in to the existence of the fire work manager.
Unfortunately, I get an unhandled exception error at this point and I'm not sure why...
timeDifference = difftime(time(&currentTime),initTime) * 1000;
here is the header file:
#ifndef FWORKMANAGER_H
#define FWORKMANAGER_H
#include <Time.h>
#include <vector>
#include "firework.h"
class fworkManager
{
private:
time_t initTime;
time_t currentTime;
double timeDifference;
std::vector<firework*> inactiveFireworks;
std::vector<firework*> activeFireworks;
std::vector<firework*> depletedFireworks;
public:
fworkManager(std::vector<firework*> fListIn);
void drawAllFireworks();
void evolve();
void fireInactiveFireworks();
void moveActiveFireworks();
void moveDepletedFireworks();
void reset();
};
#endif
And here is the CPP.
#include <vector>
#include "LUtil.h"
#include "fworkManager.h"
fworkManager :: fworkManager(std::vector<firework*> fListIn){
inactiveFireworks = fListIn;
time (&initTime);
}
//animates fireworks
void fworkManager::evolve(){
//check time against inactiveFireworks
fireInactiveFireworks();
moveActiveFireworks();
moveDepletedFireworks();
reset();
}
//draws fireworks as they come up
void fworkManager::drawAllFireworks()
{
std::vector<firework*>::iterator i;
for(i=activeFireworks.begin(); i != activeFireworks.end(); i ++)
{
(*i) -> draw();
}
}
//if fireworks are ready to fire, push them to active list
void fworkManager::fireInactiveFireworks()
{
timeDifference = difftime(time(&currentTime),initTime) * 1000;
std::vector<firework*>::iterator i;
for(i = inactiveFireworks.begin(); i != inactiveFireworks.end();)
{
if((*i) -> getBegin() <= timeDifference)
{
activeFireworks.push_back(*i);
(*i) -> explode();
i = inactiveFireworks.erase(i);
}else{
++i;
}
}
}
//animate each firework in the active list
void fworkManager::moveActiveFireworks()
{
std::vector<firework*>::iterator i;
for(i = activeFireworks.begin(); i != activeFireworks.end(); i++)
{
(*i) -> evolve();
}
}
//move fireworks that have met their duration requirement to the depleted list.
void fworkManager::moveDepletedFireworks()
{
std::vector<firework*>::iterator i;
for(i = activeFireworks.begin(); i != activeFireworks.end();)
{
if((*i) -> getLifeSpan() >= (*i) -> getDuration() )
{
depletedFireworks.push_back(*i);
i = activeFireworks.erase(i);
}else{
++i;
}
}
}
//repopulates the inactive firework list and resets the time difference. Allows animation to loop.
void fworkManager::reset()
{
if(inactiveFireworks.empty() && activeFireworks.empty())
{
time (&initTime);
std::vector<firework*>::iterator i;
for(i=depletedFireworks.begin(); i != depletedFireworks.end();)
{
(*i) -> reset();
inactiveFireworks.push_back(*i);
i = depletedFireworks.erase(i);
}
}
}
Many Thanks for any insight offered.