I am currently using for loops to check and display sprites in my game. The game feels laggy sometimes, I believe this is mostly due to amount of for loops I am using. I'm new to C++, what are the possibilities in this case?
int main()
{
sf::Texture mPlayerTexture;
sf::Sprite mPlayer;
sf::Texture mBackgroundTexture;
sf::Sprite mBackground;
Bullet bullet(0, bulletSpeed);
sf::RenderWindow window(sf::VideoMode(game->getWindowWidth(), game->getWindowHeight()), "SFML Application");
//static const sf::Time TimePerFrame;
window.setVerticalSyncEnabled(true);
//window.setFramerateLimit(60); // Added this
if (!mPlayerTexture.loadFromFile("Media/Textures/PixelSpaceships/blue_01.png"))
{
// Handle loading error
}
if (!mBackgroundTexture.loadFromFile("Media/Textures/Space.jpg")) {
// Handle loading error
}
// Set Texture and Position for Background
mBackground.setTexture(mBackgroundTexture);
mBackground.setOrigin(game->getWindowWidth() / 2.f, game->getWindowHeight() / 2.f);
mBackground.setPosition(game->getWindowWidth() / 2.f, game->getWindowHeight() / 2.f);
// Set Texture and Position for Player
mPlayer.setTexture(mPlayerTexture);
mPlayer.setOrigin(24.f, 24.f);
mPlayer.setPosition(game->getWindowWidth() / 2.f, game->getWindowHeight() / 2.f);
//enemy.enemyInstantiator(2, 100.f, 50.f);
//enemyInstantiator(10, 100.f, 150.f);
// Statistics Initialisation
sf::Font mFont;
sf::Text mStatisticsText;
mFont.loadFromFile("Media/Sansation.ttf");
mStatisticsText.setFont(mFont);
mStatisticsText.setPosition(5.f, 5.f);
mStatisticsText.setCharacterSize(10);
// Enemy Creation // Separate method in main
std::vector<Enemy> *enemyList = new std::vector<Enemy>();
float xPosition = 100.f;
float yPosition = 50.f;
float yOffset = 50.f;
float xOffset = 60.f;
for (int i = 0; i < NUMBER_OF_ALIENS; i++) {
Enemy alien(i, enemySpeed);
alien.getSprite().setOrigin(24.f, 24.f);
alien.setLocation(xPosition + (i * xOffset), yPosition);
alien.getSprite().setRotation(180.f);
enemyList->push_back(alien);
//std::cout << "I have " << enemyList->size() << " spaceships" << std::endl;
}
//std::cout << "I have " << enemyList->size() << " spaceships";
/*
//create a an array of enemys
Enemy alienArray = new Enemy[];
for (int i = 0; i < NUMBER_OF_ALIENS; i++)
{
Enemy alien(i, enemySpeed);
alien.setLocation(i * 50.f + 50.f, alien.getSprite().getGlobalBounds().height / 2);
alienArray;
}
*/
//game->run();
// Measure elapsed time
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
// something here or within the window is open needs to happen to select whether to view or play
// menu needs to happen over here or within
while (window.isOpen())
{
// Puts the time counter back to zero and also returns the time elapsed since the clock was started
sf::Time deltaTime = clock.restart();
timeSinceLastUpdate += deltaTime;
while (timeSinceLastUpdate > TimePerFrame) // fixed time steps
{
timeSinceLastUpdate -= TimePerFrame; // solves problem with variable delta time, each frame is unique
processEvents(window);
//update(TimePerFrame);
// Player 1 movement
sf::Vector2f movement(0.f, 0.f);
if (mIsMovingUp)
movement.y -= playerSpeed;
if (mIsMovingDown)
movement.y += playerSpeed;
if (mIsMovingLeft)
movement.x -= playerSpeed;
if (mIsMovingRight)
movement.x += playerSpeed;
if (mIsShooting) {
if (!bullet.isAlive()) // && !gameOver
{
bullet.spawn(true);
bullet.setLocation(mPlayer.getPosition().x - 13.f, mPlayer.getPosition().y - 24.f); // mPlayer.getPosition().x + 24 (offset) if origin is not set to center
}
}
// shooting logic
// Possibly this will be the data that needs to be sent to server
mPlayer.move(movement * TimePerFrame.asSeconds()); // Time.deltaTime frame independent movement
// for each player eventually
screenBound(mPlayer);
// screenbound enemies or else check that they do not go off bounds and change direction
// Enemy Behaviour // Move to separate method
sf::Vector2f enemyMovement(1.f, 0.f);
float yOffset = 50.f;
float xOffset = 60.f;
// Be careful with iterators as when deleting it will automatically jump to the next item in vector
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) // CAUTION & solved everything again - lesson in C++, if we don't get address, we always create a copy and modify it, which is not what we want
{
std::cout << "Direction before working move " << direction << std::endl;
i->getSprite().move(enemyMovement * direction); // Issue detected direction only changing sign if greater or less than screen bounds once
if (i->getSprite().getPosition().x + i->getSprite().getLocalBounds().width / 2 > game->getWindowWidth() ||
i->getSprite().getPosition().x - i->getSprite().getLocalBounds().width / 2 < game->getWindowWidth() - game->getWindowWidth()) { // this will be 0
direction = -(direction);
std::cout << "Direction inside if statement " << direction << std::endl;
// another for loop move all down by yOffset
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
i->getSprite().setPosition(i->getSprite().getPosition().x, i->getSprite().getPosition().y + yOffset);
//enemy.move(0.f, enemy.getPosition().y + yOffset);
}
//enemy.setPosition(enemy.getPosition().x, enemy.getPosition().y + yOffset); // y axis is inverted in SFML
//return 0; // move to separate method
}
if (i->getSprite().getPosition().y > game->getWindowHeight() - mPlayer.getLocalBounds().height) {
//removeEnemy(enemy);
// ALIVE is false, then draw based on whether alien is alive or not
std::cout << "Everyone should be dead game over!" << std::endl;
return 0; // change state to paused
}
}
}
updateStatistics(deltaTime, mStatisticsText);
// Render All
// Remember draw order is important
window.clear();
window.draw(mBackground);
window.draw(mPlayer);
window.draw(mStatisticsText);
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
if (i->isAlive()) {
i->draw(window);
std::cout << "Enemy " << i->getID() << " position - " << i->getLocation().x << " " << i->getLocation().y << std::endl;
}
}
if (bullet.isAlive()) // && !gameOver
{
//draw bullet
bullet.draw(window);
//move bullet
bullet.getSprite().move(0.f, -20);
}
//test collision with bullet and boundary
if (bullet.getSprite().getPosition().y < 0)
bullet.kill();
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
if (CollisionManager::collidesWith(mPlayer, *i) && i->isAlive()) { // *i it points to the enemy, and will give me an enemy
std::cout << "You're dead!" << std::endl;
return 0; //-> I'm dead gameOver = true;
}
}
//for (Enemy& enemy : enemyList) {
// if (enemy.isAlive()) {
// enemy.draw(window);
// }
//}
//enemy.render(alienArray, mWindow);
/*
for (int i = 0; i < mEnemies.size(); i++)
{
sf::Sprite temp = mEnemies.at(i);
mWindow.draw(temp);
}
*/
window.display();
}
return 0;
}
void processEvents(sf::RenderWindow& window) {
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::KeyPressed:
handlePlayerInput(event.key.code, true);
break;
case sf::Event::KeyReleased:
handlePlayerInput(event.key.code, false);
break;
case sf::Event::Closed:
window.close();
break;
}
}
}
void handlePlayerInput(sf::Keyboard::Key key, bool isPressed)
{
if (key == sf::Keyboard::W || key == sf::Keyboard::Up)
mIsMovingUp = isPressed;
else if (key == sf::Keyboard::S || key == sf::Keyboard::Down)
mIsMovingDown = isPressed;
else if (key == sf::Keyboard::A || key == sf::Keyboard::Left)
mIsMovingLeft = isPressed;
else if (key == sf::Keyboard: || key == sf::Keyboard::Right)
mIsMovingRight = isPressed;
else if (key == sf::Keyboard::Space) {
mIsShooting = isPressed;
std::cout << "Spacebar was pressed!" << std::endl;
}
}