Hi all,
I've implemented a demo project to scroll across a Tiled map editor level (using a loader by a fellow on the forums named Quinn. Thanks!).
It's loading the tiles fine, but while scrolling, it seems quite jerky. I'm really looking for a bit of a sanity check to make sure I'm using some of the SFML features with best practices in mind:
Main loop:#include <SFML/Graphics.hpp>
#include "level.h"
sf::Rect<float> GetViewportRect(sf::View& v)
{
return sf::Rect<float>(
v.getCenter().x - (v.getSize().x / 2),
v.getCenter().y - (v.getSize().y / 2),
v.getSize().x,
v.getSize().y);
}
int main()
{
sf::RenderWindow window(sf::VideoMode(1280,640), "Sandbox!", sf::Style::Fullscreen);
window.setFramerateLimit(30);
nelsk::Level _level;
_level.LoadFromFile("Level1.tmx");
sf::Rect<float> r(500,640,1280,640);
sf::View v(r);
_level.SetDrawingBounds(r);
window.setView(v);
sf::Vector2f moveVec;
sf::Clock _clock;
float _deltaT;
float fps;
while(window.isOpen())
{
_deltaT = _clock.restart().asSeconds();
fps = 1.f / _deltaT;
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed ||
sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
moveVec.x = 400 * _deltaT;
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
moveVec.x = -400 * _deltaT;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
moveVec.y = 400 * _deltaT;
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
moveVec.y = -400 *_deltaT;
v.move(moveVec);
window.setView(v);
_level.SetDrawingBounds(GetViewportRect(v));
window.clear();
_level.Draw(window);
// Draw sprites to render frame
window.display();
moveVec.x = 0; moveVec.y = 0;
}
return EXIT_SUCCESS;
}
Relevent from Level.cpp
struct Layer{
int opacity;
std::vector <sf::Sprite> tiles;
};
void Level::SetDrawingBounds(sf::Rect<float> bounds)
{
drawingBounds = bounds;
//Adjust the rect so that tiles are drawn just off screen, so you don't see them disappearing.
drawingBounds.top -= tileHeight;
drawingBounds.left -= tileWidth;
drawingBounds.width += tileWidth;
drawingBounds.height += tileHeight;
}
void Level::Draw(sf::RenderWindow &window)
{
for (int layer = 0; layer < layers.size(); layer++)
{
for (int tile = 0; tile < layers[layer].tiles.size(); tile++)
{
if (drawingBounds.contains(layers[layer].tiles[tile].getPosition().x, layers[layer].tiles[tile].getPosition().y))
{
window.draw(layers[layer].tiles[tile]);
}
}
}
}
Is there anything obviously wrong with this approach?
Side question: Perhaps this is a misunderstanding on my part (likely), but why does a RenderWindow not hold a reference to a view, rather than setting the view each loop through?
My fps is reporting very close to 30 and is pretty consistent, but every so often it will drop to around 19 for a couple loops. (I'm only running VStudio 2010 and my app on a pretty powerful rig)
Where should I start to smooth out this scrolling? (I've also got some pretty terrible tearing issues).