Inspired by the fact, that google let this problem seem a general one, I thought about that "adding pixels to each tile"-solution and came up with this: let the game add the pixels when loading the tileset. It seems to work perfectly
Also the code for preparing the tile changed. Here's my solution:
void scale(sf::Vector2f& v, sf::Vector2u const & tile_size) {
v.x *= tile_size.x;
v.y *= tile_size.y;
}
void prepare(sf::Vector2f& tl, sf::Vector2f& tr, sf::Vector2f& br, sf::Vector2f& bl, sf::Vector2u const & offset, sf::Vector2u const & tile_size) {
tl = sf::Vector2f(offset.x, offset.y);
tr = sf::Vector2f(offset.x + 1.f, offset.y);
br = sf::Vector2f(offset.x + 1.f, offset.y + 1.f);
bl = sf::Vector2f(offset.x, offset.y + 1.f);
scale(tl, tile_size);
scale(tr, tile_size);
scale(br, tile_size);
scale(bl, tile_size);
}
void add(sf::VertexArray& array, sf::Vector2u const & world_pos, sf::Vector2u const & tile_offset, sf::Vector2u const & tile_size) {
sf::Vertex tl, tr, br, bl; // [t]op[r]ight etc.
// setup positions and texture coords
prepare(tl.position, tr.position, br.position, bl.position, world_pos, tile_size);
prepare(tl.texCoords, tr.texCoords, br.texCoords, bl.texCoords, tile_offset, tile_size);
// fix tex coords to suit the modified atlas
sf::Vector2f delta{1.f, 1.f};
delta.x += tile_offset.x * 2;
delta.y += tile_offset.y * 2;
tl.texCoords += delta;
tr.texCoords += delta;
br.texCoords += delta;
bl.texCoords += delta;
// add tiles
array.append(tl);
array.append(tr);
array.append(br);
array.append(bl);
}
sf::Image rebuildAtlas(sf::Image const & source, sf::Vector2u const & tilesize) {
// determine new size
auto size = source.getSize();
assert(size.x % tilesize.x == 0);
assert(size.y % tilesize.y == 0);
auto num_x = size.x / tilesize.x;
auto num_y = size.y / tilesize.y;
size.x += num_x * 2;
size.y += num_y * 2;
sf::Image atlas;
atlas.create(size.x, size.y);
// create atlas
sf::Vector2u offset;
for (offset.y = 0u; offset.y < num_y; ++offset.y) {
for (offset.x = 0u; offset.x < num_x; ++offset.x) {
// copy frame
auto destX = 1 + offset.x * (tilesize.x + 2);
auto destY = 1 + offset.y * (tilesize.y + 2);
sf::IntRect sourceRect;
sourceRect.left = offset.x * tilesize.x;
sourceRect.top = offset.y * tilesize.y;
sourceRect.width = tilesize.x;
sourceRect.height = tilesize.y;
atlas.copy(source, destX, destY, sourceRect);
// create left border
--destX;
sourceRect.width = 1;
atlas.copy(source, destX, destY, sourceRect);
// create right border
destX += tilesize.x + 1;
sourceRect.left += tilesize.x - 1;
atlas.copy(source, destX, destY, sourceRect);
// create top border (copying from source to source!)
destX -= tilesize.x + 1;
sourceRect.left = destX;
sourceRect.top = destY;
sourceRect.width = tilesize.x + 2;
sourceRect.height = 1;
--destY;
atlas.copy(atlas, destX, destY, sourceRect);
// create bottom border (copying from source to source!)
destY += tilesize.x;
sourceRect.top = destY;
++destY;
atlas.copy(atlas, destX, destY, sourceRect);
}
}
return atlas;
};