Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Game feels laggy, alternative to for loops for game logic and rendering?  (Read 1476 times)

0 Members and 1 Guest are viewing this topic.

firepro20

  • Newbie
  • *
  • Posts: 22
    • View Profile
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?

Quote
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::D || key == sf::Keyboard::Right)
      mIsMovingRight = isPressed;
   else if (key == sf::Keyboard::Space) {
      mIsShooting = isPressed;
      std::cout << "Spacebar was pressed!" << std::endl;
   }
}