Gosh that's really hard to see because youtube lowers video quality... I'll try to descibe the issue better, also there's another upload on yt and an mp4 as an attachment.
Some tiles are drawn out of place, I don't know how to call this, It's like if there was a line 100px or so from the bottom of the window, every tile under that line is drawn out of place when the view moves.
Like if there was some kind of lag in the drawing process. This appens only when the view moves (it follows player position) higher speed = more lag and more offset in the drawning.
I'm not doing anything fancy and this never happened in other games which share basic code with this one. Also it does not only happen with tiles, but with every sprite I draw. Tried running both with internal intel GPU and Nvidia, unfortunately I can't test this on other machines or Windows/Mac so I can't event figure out if it's my platform (ArchLinux 64 bit, intel/nvidia drivers, latest sfml binaries).
I think it could have more to do with the view moving than with the textures because I tried changing pngs, drawing only one large sprite instead of multiple tiles in a loop, enabling/disabling vsync and texture smoothing... This is a nasty one, I can't figure out how to debug it because sprites position it's ok It's like there were 2 buffers, one on top of that line and another on the bottom...
Try looking at the far left/right of the screen, where the tiles end, you can see some of them are out of place, with an offset of like 20px on the opposite direction.
Also here's the class which is causing this madness.
#include "Zone.hpp"
#include "Debug.h"
Zone::Zone(State::Context con, ZoneData ld)
:context{con}
{
textures.load("LevelSheet", ld.getSheet());
textures.load("Player", "img/player.png");
textures.get("LevelSheet").setSmooth(false);
bounds = sf::IntRect{0, 0, ld.getWidth(), ld.getHeight()};
sf::Vector2u tileSheetSize = textures.get("LevelSheet").getSize();
int tileSize = ld.getTileSize();
int maxTilesInRow = tileSheetSize.x / tileSize;
map2Layer(ld.getMap(), bgLayer, tileSize, maxTilesInRow);
map2Layer(ld.getCollidables(), collidablesLayer, tileSize, maxTilesInRow);
player.setTexture(textures.get("Player"), {0,0,tileSize, tileSize});
player.setPosition(ld.getSpawnPosition().x, ld.getSpawnPosition().y);
drawOffset = tileSize * 30;
worldView.zoom(.5);
worldView.setSize(context.window->getSize().x/2, context.window->getSize().y/2);
worldView.setCenter(player.getPosition());
}
void Zone::update(sf::Time deltaT)
{
player.handleInput(bounds);
}
void Zone::draw()
{
worldView.setCenter(player.getPosition());
context.window->setView(worldView);
for (auto &tile : bgLayer)
if (isInBounds(tile))
context.window->draw(tile);
for (auto obj : collidablesLayer)
if (isInBounds(obj))
context.window->draw(obj);
context.window->draw(player);
}
void Zone::handleEvent(const sf::Event& event)
{
}
bool Zone::isInBounds(sf::Sprite& tile)
{
//TILE LEFT X IS > WORLD LEFT X (WORLD CENTER X - HALF WORLD WIDTH)
bool inLeft = tile.getPosition().x >= worldView.getCenter().x - (worldView.getSize().x/2 + drawOffset);
//TILE LEFT X IS < WORLD RIGHT X (WORLD CENTER X + HALF WORLD WIDTH)
bool inRight = tile.getPosition().x <= worldView.getCenter().x + (worldView.getSize().x/2 + drawOffset);
//TILE TOP Y > WORLD TOP Y (WORLD CENTER Y - HALF WORLD HEIGHT)
bool inTop = tile.getPosition().y >= worldView.getCenter().y - (worldView.getSize().y/2 + drawOffset);
//TILE BOTTOM Y < WORLD BOTTOM Y (WORLD CENTER Y + HALF WORLD HEIGHT)
bool inBottom = tile.getPosition().y <= worldView.getCenter().y + (worldView.getSize().y/2 + drawOffset);
if (inLeft && inRight && inTop && inBottom)
return true;
return false;
}
void Zone::map2Layer(const std::vector<std::vector<int>> &source, std::vector<sf::Sprite> &destination, int tileSize, int rowMax)
{
for (int i = 0; i < source.size(); i++)
for (int j = 0; j < source[i].size(); j++)
if (source[i][j] >= 0)
{
sf::Vector2i tilePosition = {source[i][j] * tileSize, (source[i][j] * tileSize) % rowMax};
sf::Sprite tile{textures.get("LevelSheet"), {tilePosition, {tileSize, tileSize}}};
tile.setPosition({j * tileSize * 1.f, i * tileSize * 1.f});
destination.push_back(tile);
}
}