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*)