0
\$\begingroup\$

I am making a 2D top-down game in C++ and the graphics library SFML.

I have designed a chunk system by myself and have successfully made it so that when a chunk is off-screen, it isn't rendered, to allow bigger maps to be used without rendering every tile on the map, which would/could cause lag.

All this works fine, but the deltatime is slowed down, I think.

What happens is that the player presses 'wasd', this then moves the map in the opposite direction, e.g. 'w' moves the map down to act like the player is moving up on the map etc.

I'll put the code that handles whether a chunk should be rendered or not:

for(std::list<shared_ptr<Entity>>::const_iterator i=this->entities.begin(); i != this->entities.end(); ++i) {
    (*i)->tick(dt, *this);
    if((*i)->id == entityState::player) {
        Handler::playerVelX = -(*i)->velX;
        Handler::playerVelY = -(*i)->velY;
    }
 }      

for(std::list<shared_ptr<Map>>::const_iterator j=this->maps.begin(); j != this->maps.end(); ++j) {
    (*j)->x += std::round(Handler::playerVelX);
    (*j)->y += std::round(Handler::playerVelY);
    view.setPosition(-(std::round(Handler::playerVelX)), -(std::round(Handler::playerVelY)));
    int vx = view.getX();
    int vy = view.getY();
    int vw = view.getWidth();
    int vh = view.getHeight();
    for(std::list<shared_ptr<Chunk>>::const_iterator i=this->chunks.begin(); i != this->chunks.end(); ++i) {
        (*i)->tick();
        (*i)->x = (*j)->x + ((*i)->cx * TileSprites::width * TileSprites::scaleX);
        (*i)->y = (*j)->y + ((*i)->cy * TileSprites::height * TileSprites::scaleY);

        int x = (*i)->x;
        int y = (*i)->y;
        int w = (*i)->width;
        int h = (*i)->height;

        if(x + w < vx || x > vx + vw || y + h < vy || y > vy + vh) {
            if((*i)->loaded) { (*i)->loaded = false; }
        } else { if((*i)->loaded == false) { (*i)->loaded = true; } }
    }
}

The view is the 'camera' that follows the player around the map, which lets me decide where the player is according to the map.

The map has an x and a y, the viewport x is the negative of map x and the same for the y.

The (*i)->cx is the chunks position that corresponds to the initial position of the chunk in the map, whereas the (*i)->x is the current position on the screen.

As I said, this all works fine but I thought I should explain the variables.

In the player tick(), this is the movement code. Keep in mind that the other keyboard handling is not shown, as this is the part that handles the movement:

if(keys[Keyboard::W]) { Player::velY = -180 * dt.asSeconds(); }
if(keys[Keyboard::S]) { Player::velY = 180 * dt.asSeconds(); }
if(keys[Keyboard::A]) { Player::velX = -180 * dt.asSeconds(); }
if(keys[Keyboard::D]) { Player::velX = 180 * dt.asSeconds(); }

Below is the main game loop. As this is my first game project, I'm not really sure how to make an engine in c++, although I've used the 'notch' engine in Java, so this engine might be fine but I feel like more is needed:

void Game::run() {
    sf::Clock gameClock;
    float lastTime = 0;
    while(window.window.isOpen()) {
        sf::Event event;
        while(window.window.pollEvent(event)) {
            if(event.type == sf::Event::Closed) {
                window.window.close();
            }
        }
        sf::Time dt = gameClock.restart();

        float currentTime = dt.asSeconds();
        float fps = 1.f / currentTime;
        lastTime = currentTime;
        std::cout << "FPS: " << fps << std::endl;

        this->tick(dt);

        window.window.clear(sf::Color(this->backgroundColor));

        this->render();

        window.window.display();
    }
}

My problem is: when a chunk or multiple chunks aren't being rendered due to the (*i)->loaded = false part, my player moves slower than before, but the FPS that is printed is the same.


The profiler:

This isnt a HTML snippet I've just put the profiler message there so it doesnt make the question absurdly long.

The above isnt a HTML snippet but the profiler.
 %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name    
 15.62      0.30     0.30                             Chunk::render(sf::RenderWindow&)
 13.02      0.55     0.25                             std::__shared_ptr<Tile, (__gnu_cxx::_Lock_policy)2>::get() const
 10.42      0.75     0.20                             sf::Sprite::operator=(sf::Sprite const&)
  9.38      0.93     0.18                             std::_List_const_iterator<std::shared_ptr<Tile> >::operator*() const
  8.33      1.09     0.16                             std::__shared_ptr_access<Tile, (__gnu_cxx::_Lock_policy)2, false, false>::operator->() const
  7.29      1.23     0.14                             __gnu_cxx::__aligned_membuf<std::shared_ptr<Tile> >::_M_ptr() const
  7.29      1.37     0.14                             __gnu_cxx::__aligned_membuf<std::shared_ptr<Tile> >::_M_addr() const
  6.77      1.50     0.13                             sf::Transformable::operator=(sf::Transformable const&)
  6.77      1.63     0.13                             std::_List_node<std::shared_ptr<Tile> >::_M_valptr() const
  5.73      1.74     0.11                             std::__shared_ptr_access<Tile, (__gnu_cxx::_Lock_policy)2, false, false>::_M_get() const
  2.08      1.78     0.04                             std::_List_const_iterator<std::shared_ptr<Tile> >::operator++()
  1.56      1.81     0.03                             std::_List_iterator<std::shared_ptr<Tile> >::_List_iterator(std::__detail::_List_node_base*)
  1.56      1.84     0.03                             std::operator!=(std::_List_const_iterator<std::shared_ptr<Tile> > const&, std::_List_const_iterator<std::shared_ptr<Tile> > const&)
  0.52      1.85     0.01                             sf::Transformable::setPosition(float, float)
  0.52      1.86     0.01                             sf::Transformable::setScale(float, float)
  0.52      1.87     0.01                             sf::Drawable::operator=(sf::Drawable const&)
  0.52      1.88     0.01                             std::_List_const_iterator<std::shared_ptr<Tile> >::_List_const_iterator(std::_List_iterator<std::shared_ptr<Tile> > const&)
  0.52      1.89     0.01                             std::vector<int, std::allocator<int> >::operator[](unsigned int)
  0.52      1.90     0.01                             std::__cxx11::list<std::shared_ptr<Tile>, std::allocator<std::shared_ptr<Tile> > >::end()
  0.52      1.91     0.01                             __gthr_win32_once
  0.52      1.92     0.01                             _fu19___ZN2sf12RenderStates7DefaultE
  0.00      1.92     0.00     1157     0.00     0.00  Player::tick(sf::Time, Handler&)
  0.00      1.92     0.00     1157     0.00     0.00  Player::render(sf::RenderWindow&)
  0.00      1.92     0.00        4     0.00     0.00  __gnu_cxx::new_allocator<sf::Sprite>::new_allocator(__gnu_cxx::new_allocator<sf::Sprite> const&)
  0.00      1.92     0.00        3     0.00     0.00  std::allocator<sf::Sprite>::~allocator()
  0.00      1.92     0.00        2     0.00     0.00  std::initializer_list<sf::Sprite>::begin() const
  0.00      1.92     0.00        2     0.00     0.00  std::allocator<sf::Sprite>::allocator(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        2     0.00     0.00  std::allocator<sf::Sprite>::allocator(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        2     0.00     0.00  std::_Vector_base<sf::Sprite, std::allocator<sf::Sprite> >::_Vector_impl::_Vector_impl(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  Entity::Entity()
  0.00      1.92     0.00        1     0.00     0.00  Entity::~Entity()
  0.00      1.92     0.00        1     0.00     0.00  Player::Player(int, int)
  0.00      1.92     0.00        1     0.00     0.00  Player::~Player()
  0.00      1.92     0.00        1     0.00     0.00  Player::~Player()
  0.00      1.92     0.00        1     0.00     0.00  Collision::Collision()
  0.00      1.92     0.00        1     0.00     0.00  __gnu_cxx::__alloc_traits<std::allocator<sf::Sprite>, sf::Sprite>::_S_select_on_copy(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  std::initializer_list<sf::Sprite>::end() const
  0.00      1.92     0.00        1     0.00     0.00  std::initializer_list<sf::Sprite>::size() const
  0.00      1.92     0.00        1     0.00     0.00  std::allocator<sf::Sprite>::allocator()
  0.00      1.92     0.00        1     0.00     0.00  std::_Vector_base<sf::Sprite, std::allocator<sf::Sprite> >::_M_create_storage(unsigned int)
  0.00      1.92     0.00        1     0.00     0.00  std::_Vector_base<sf::Sprite, std::allocator<sf::Sprite> >::_Vector_base(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  std::_Vector_base<sf::Sprite, std::allocator<sf::Sprite> >::_Vector_base(unsigned int, std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  std::allocator_traits<std::allocator<sf::Sprite> >::select_on_container_copy_construction(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  std::allocator_traits<std::allocator<sf::Sprite> >::max_size(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  sf::Sprite* std::__uninitialized_copy<false>::__uninit_copy<sf::Sprite const*, sf::Sprite*>(sf::Sprite const*, sf::Sprite const*, sf::Sprite*)
  0.00      1.92     0.00        1     0.00     0.00  std::vector<sf::Sprite, std::allocator<sf::Sprite> >::_S_max_size(std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  std::vector<sf::Sprite, std::allocator<sf::Sprite> >::_S_check_init_len(unsigned int, std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  void std::vector<sf::Sprite, std::allocator<sf::Sprite> >::_M_range_initialize<sf::Sprite const*>(sf::Sprite const*, sf::Sprite const*, std::forward_iterator_tag)
  0.00      1.92     0.00        1     0.00     0.00  std::vector<sf::Sprite, std::allocator<sf::Sprite> >::vector(std::vector<sf::Sprite, std::allocator<sf::Sprite> > const&)
  0.00      1.92     0.00        1     0.00     0.00  std::vector<sf::Sprite, std::allocator<sf::Sprite> >::vector(std::initializer_list<sf::Sprite>, std::allocator<sf::Sprite> const&)
  0.00      1.92     0.00        1     0.00     0.00  std::iterator_traits<sf::Sprite const*>::difference_type std::__distance<sf::Sprite const*>(sf::Sprite const*, sf::Sprite const*, std::random_access_iterator_tag)
  0.00      1.92     0.00        1     0.00     0.00  sf::Sprite* std::uninitialized_copy<sf::Sprite const*, sf::Sprite*>(sf::Sprite const*, sf::Sprite const*, sf::Sprite*)
  0.00      1.92     0.00        1     0.00     0.00  std::iterator_traits<sf::Sprite const*>::iterator_category std::__iterator_category<sf::Sprite const*>(sf::Sprite const* const&)
  0.00      1.92     0.00        1     0.00     0.00  sf::Sprite* std::__uninitialized_copy_a<sf::Sprite const*, sf::Sprite*, sf::Sprite>(sf::Sprite const*, sf::Sprite const*, sf::Sprite*, std::allocator<sf::Sprite>&)
  0.00      1.92     0.00        1     0.00     0.00  std::iterator_traits<sf::Sprite const*>::difference_type std::distance<sf::Sprite const*>(sf::Sprite const*, sf::Sprite const*)

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

After looking around for a while I have come to another solution, that solution was to use another game loop, I've instead gone for the Gaffer on Games loop, this now works fine but if I go back to the old loop it no longer works.

Here is my new game loop, its not perfect as I havent completely got my head around loops yet, but here it is:

double t = 0.0;
double dt = 0.01;

double currentTime = Game::clock.restart().asSeconds();
double accumulator = 0.0;

while ( Game::window.window.isOpen()) {

    double newTime = Game::clock.getElapsedTime().asSeconds();
    double frameTime = newTime - currentTime;

    while(Game::window.window.pollEvent(Game::event)) {
        if(Game::event.type == sf::Event::Closed) {
            window.window.close();
        }
    }
    if ( frameTime > 0.25f )
        frameTime = 0.25f;
    currentTime = newTime;

    accumulator += frameTime;

    while ( accumulator >= dt ) {
        Game::tick(dt);
        t += dt;
        accumulator -= dt;
    }

    Game::window.clear();
    Game::render();
    Game::window.window.display();
}

The only part that doesn't make sense to me is the currentTime and newTime, it seems in my head like they are switched around, but when I do switch them the window doesn't respond.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .