#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <fstream>
int main(){
sf::RenderWindow window(sf::VideoMode(800, 600), "Tilemap");
sf::View view(sf::Vector2f(2000, 2000), sf::Vector2f(window.getSize())); //The Main View
sf::View minimap(view.getCenter(), view.getSize()*2.f); //Secondary View, a minimap
minimap.setViewport(sf::FloatRect(0.75f, 0, 0.25f, 0.25f));
sf::Texture tileset;
tileset.loadFromFile("terrain.png");
sf::Vector2i tim(300, 300); //Tiles in Map
sf::Vector2i tis(10, 10); //Tiles in Screen
sf::Vector2i tiz = tis + sf::Vector2i(3, 3); // Tiles in Zone. Zone is the area loaded and visible.
sf::Vector2i tile_size(view.getSize().x/tis.x, view.getSize().y/tis.y);
sf::Vector2i tex_tile_size(tileset.getSize()/16u);
sf::Vector2f step_size(tile_size/10); //How many pixels will the View move when the user press a key
sf::Vector2i central_tile(view.getCenter().x/tile_size.x, view.getCenter().y/tile_size.y); //The tile in the center of the loaded zone
std::vector<int> tiles(tiz.x*tiz.y); //Tiles array
sf::VertexArray vertices(sf::Quads, tiz.x*tiz.y*4); //Vertices to represent the tiles visually
std::ifstream map_file;
map_file.open("map.data", std::ifstream::binary);
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if(event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
view.move(-step_size.x, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
view.move(+step_size.x, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
view.move(0, -step_size.y);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
view.move(0, +step_size.y);
}
const sf::Vector2i current_tile(view.getCenter().x/tile_size.x, view.getCenter().y/tile_size.y);
if (current_tile != central_tile){ //check if the player moved from one tile to another
const sf::Vector2i zone_origin(central_tile.x-tiz.x/2, central_tile.y-tiz.y/2); //the first tile of the zone, upper left
const sf::Vector2i zone_end(zone_origin + tiz); //the last tile of the zone, bottom right
int k = 0;
for (int y = zone_origin.y; y <= zone_end.y; y++){
const int x = zone_origin.x;
map_file.seekg((y*tim.x+x)*sizeof(tiles[0]), std::ios_base::beg);
map_file.read(reinterpret_cast<char*> (&tiles[tiz.x*k]), tiz.x*sizeof(tiles[0])); //load array from binary file
k++;
}
for (int y=0; y<tiz.y; y++){
for (int x=0; x<tiz.x; x++){
const int n = y*tiz.x+x;
sf::Vertex* quad = &vertices[n*4];
quad[0].position = sf::Vector2f((x+zone_origin.x)*tile_size.x, (y+zone_origin.y)*tile_size.y);
quad[1].position = sf::Vector2f((x+zone_origin.x+1)*tile_size.x, (y+zone_origin.y)*tile_size.y);
quad[2].position = sf::Vector2f((x+zone_origin.x+1)*tile_size.x, (y+zone_origin.y+1)*tile_size.y);
quad[3].position = sf::Vector2f((x+zone_origin.x)*tile_size.x, (y+zone_origin.y+1)*tile_size.y);
const int tile_id = tiles[n];
const int tx = tile_id % (tileset.getSize().x / tex_tile_size.x);
const int ty = tile_id / (tileset.getSize().x / tex_tile_size.x);
quad[0].texCoords = sf::Vector2f(tx*tex_tile_size.x, ty*tex_tile_size.y);
quad[1].texCoords = sf::Vector2f((tx+1)*tex_tile_size.x, ty*tex_tile_size.y);
quad[2].texCoords = sf::Vector2f((tx+1)*tex_tile_size.x, (ty+1)*tex_tile_size.y);
quad[3].texCoords = sf::Vector2f(tx*tex_tile_size.x, (ty+1)*tex_tile_size.y);
}
}
central_tile = current_tile;
}
window.clear(sf::Color::White);
window.setView(view);
window.draw(vertices, &tileset);
minimap.setCenter(view.getCenter());
window.setView(minimap);
window.draw(vertices, &tileset);
window.display();
sf::sleep(sf::milliseconds(10));
}
return 0;
}