tBane Temat założony przez niniejszego użytkownika |
[SFML] Mapa kafelkowa - czyli jak to zrobić dobrze » 2024-06-24 12:52:28 Witam. Piszę system mapy kafelkowej i chciałbym to dobrze zrobić. Jakieś rady? Kod zamieszczam poniżej. #ifndef Maps_hpp #define Maps_hpp
float tileSide = 32.0f; int tilesInSideMap = 16; float mapSide = tilesInSideMap * tileSide;
enum class terrainType { grass, sands };
class Tile { public: sf::Vector2i coords; sf::Vector2f position; Texture * texture; sf::Sprite sprite; terrainType ttype; Tile( int x, int y ) { coords.x = x; coords.y = y; ttype = terrainType::grass; texture = getTexture( "assets/tiles/grass" ); } ~Tile() { } void setTerrainType( terrainType ttype ) { this->ttype = ttype; if( ttype == terrainType::grass ) texture = getTexture( "assets/tiles/grass" ); if( ttype == terrainType::sands ) texture = getTexture( "assets/tiles/sands" ); sprite.setTexture( * texture->texture ); } };
class Map { public: sf::Vector2i coords; std::vector < Tile * > tiles; Map( int x, int y ) { coords.x = x; coords.y = y; tiles.clear();; for( int y = 0; y < tilesInSideMap; y++ ) for( int x = 0; x < tilesInSideMap; x++ ) { Tile * tile = new Tile( x, y ); tile->position.x = float( coords.x ) * mapSide + float( x ) * tileSide; tile->position.y = float( coords.y ) * mapSide + float( y ) * tileSide; tile->sprite = sf::Sprite(); tile->sprite.setTexture( * tile->texture->texture ); tile->sprite.setPosition( tile->position ); tiles.push_back( tile ); } } ~Map() { } void render() { for( auto & t: tiles ) window->draw( t->sprite ); } };
class World { public: std::vector < Map * > maps; World() { maps.clear(); maps.push_back( new Map( 0, 0 ) ); maps.push_back( new Map( 1, 0 ) ); } Tile * getTile( sf::Vector2f worldPosition ) { sf::Vector2i mapCoords; mapCoords.x = worldPosition.x / mapSide; mapCoords.y = worldPosition.y / mapSide; Map * map = nullptr; for( auto & m: maps ) { if( m->coords == mapCoords ) map = m; } if( map == nullptr ) return nullptr; sf::Vector2i tileCoords; tileCoords.x = int( worldPosition.x ) % int( mapSide ) / tileSide; tileCoords.y = int( worldPosition.y ) % int( mapSide ) / tileSide; return map->tiles[ tileCoords.y * tilesInSideMap + tileCoords.x ]; } void render() { for( auto & m: maps ) { m->render(); } } };
World * world;
#endif
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-26 13:42:13 Kafelki mapy mają wymiary 16x16 px, a tekstury 64x64 px. Aby renderować mapę kafelków 16x16 px, używając tekstur o wymiarach 64x64 px, tak aby fragmenty tekstury były wyświetlane w siatce 16x16 px należy: tx = int( tile->position.x ) % tile->texture->texture->getSize().x; ty = int( tile->position.y ) % tile->texture->texture->getSize().y; tile->sprite.setTextureRect( sf::IntRect( tx, ty, tileSide, tileSide ) );
|
|
DejaVu |
» 2024-06-26 13:43:48 Offtopic: Twój projekt zaczyna nieźle wyglądać. |
|
pekfos |
» 2024-06-26 20:18:08 Ile trwa renderowanie? Robienie tego sprajtami jest zwykle wolne. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-26 21:06:01 Nawet nie mierzyłem, ponieważ renderowało płynnie. Teraz dokonałem pomiaru i wyszło całkiem nieźle. Wyniki dla 24 map (8x4) 16x16 pól: 4 ms, 0.004343 s 4 ms, 0.004179 s 4 ms, 0.004295 s 4 ms, 0.004318 s 4 ms, 0.004167 s 4 ms, 0.004141 s 4 ms, 0.004191 s 4 ms, 0.004175 s 4 ms, 0.004155 s 4 ms, 0.004133 s 4 ms, 0.004223 s 4 ms, 0.004329 s
(W sumie to mam całkiem dobrą kartę graficzną i może dlatego wyniki są dobre...?) A jest lepsza metoda renderingu map? |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-27 12:51:23 Proporcje budynków szerokość (x) x 16px wysokość h x 16px długość (x/2 + h) x 16px pozostaje jedynie zdecydować czy wszystkie budynki mają mieć tekstury o stałym rozmiarze 256x256 px czy też różne rozmiary wielokrotności 16px. A tak się to prezentuje w edytorze |
|
pekfos |
» 2024-06-27 17:41:18 |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-06-27 19:50:14 Dobra opanowane częściowo: #ifndef Maps_hpp #define Maps_hpp
float tileSide = 16.0f; int tilesInSideMap = 16; float mapSide = tilesInSideMap * tileSide;
class Tile { public: sf::Vector2i coords; sf::Vector2f position; Texture * texture; sf::Sprite sprite; terrainType ttype; Tile( int x, int y ) { coords.x = x; coords.y = y; ttype = terrainType::grass; texture = getTexture( "assets/tiles/grass" ); } ~Tile() { } void setTerrainType( terrainType ttype ) { this->ttype = ttype; if( ttype == terrainType::grass ) texture = getTexture( "assets/tiles/grass" ); if( ttype == terrainType::sands ) texture = getTexture( "assets/tiles/sands" ); if( ttype == terrainType::water ) texture = getTexture( "assets/tiles/water" ); sprite.setTexture( * texture->texture ); } };
class Map : public sf::Drawable , public sf::Transformable { public: sf::Vector2i coords; std::vector < Tile * > tiles; sf::VertexArray vertexes; Map( int x, int y ) { coords.x = x; coords.y = y; vertexes.setPrimitiveType( sf::Triangles ); vertexes.resize( tilesInSideMap * tilesInSideMap * 6 ); int coord_x, coord_y; int tu, tv; for( int y = 0; y < tilesInSideMap; y++ ) for( int x = 0; x < tilesInSideMap; x++ ) { sf::Vertex * triangles = & vertexes[( x + y * tilesInSideMap ) * 6 ]; coord_x =( coords.x * tilesInSideMap + x ); coord_y =( coords.y * tilesInSideMap + y ); triangles[ 0 ].position = sf::Vector2f( coord_x * tileSide, coord_y * tileSide ); triangles[ 1 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide ); triangles[ 2 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide ); triangles[ 3 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide ); triangles[ 4 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide ); triangles[ 5 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide,( coord_y + 1 ) * tileSide ); tu = int( coord_x * tileSide ) % 64; tv = int( coord_y * tileSide ) % 64; triangles[ 0 ].texCoords = sf::Vector2f( tu, tv ); triangles[ 1 ].texCoords = sf::Vector2f( tu + tileSide, tv ); triangles[ 2 ].texCoords = sf::Vector2f( tu, tv + tileSide ); triangles[ 3 ].texCoords = sf::Vector2f( tu, tv + tileSide ); triangles[ 4 ].texCoords = sf::Vector2f( tu + tileSide, tv ); triangles[ 5 ].texCoords = sf::Vector2f( tu + tileSide, tv + tileSide ); triangles[ 0 ].color = sf::Color::Red; } tiles.clear();; for( int y = 0; y < tilesInSideMap; y++ ) for( int x = 0; x < tilesInSideMap; x++ ) { Tile * tile = new Tile( x, y ); tile->position.x = float( coords.x ) * mapSide + float( x ) * tileSide; tile->position.y = float( coords.y ) * mapSide + float( y ) * tileSide; tile->sprite = sf::Sprite(); tile->sprite.setTexture( * tile->texture->texture ); tu = int( tile->position.x ) % tile->texture->texture->getSize().x; tv = int( tile->position.y ) % tile->texture->texture->getSize().y; tile->sprite.setTextureRect( sf::IntRect( tu, tv, tileSide, tileSide ) ); tile->sprite.setPosition( tile->position ); tiles.push_back( tile ); } } ~Map() { } void render() { } private: virtual void draw( sf::RenderTarget & target, sf::RenderStates states ) const { states.transform *= getTransform(); states.texture = & * getTexture( "assets/tiles/grass" )->texture; target.draw( vertexes, states ); } };
class World { public: std::vector < Map * > maps; World() { maps.clear(); int start_x = 4; int end_x = 11; int start_y = 7; int end_y = 10; for( int y = start_y; y <= end_y; y++ ) for( int x = start_x; x <= end_x; x++ ) maps.push_back( new Map( x, y ) ); } Map * getMap( sf::Vector2f worldPosition ) { sf::Vector2i mapCoords; mapCoords.x = worldPosition.x / mapSide; mapCoords.y = worldPosition.y / mapSide; Map * map = nullptr; for( auto & m: maps ) { if( m->coords == mapCoords ) map = m; } return map; } Tile * getTile( sf::Vector2f worldPosition ) { Map * map = getMap( worldPosition ); if( map == nullptr ) return nullptr; sf::Vector2i tileCoords; tileCoords.x = int( worldPosition.x ) % int( mapSide ) / tileSide; tileCoords.y = int( worldPosition.y ) % int( mapSide ) / tileSide; return map->tiles[ tileCoords.y * tilesInSideMap + tileCoords.x ]; } void render() { sf::Clock c; sf::Time start = c.getElapsedTime(); for( auto & m: maps ) { window->draw( * m ); } sf::Time end = c.getElapsedTime(); cout <<( end - start ).asMilliseconds() << " ms,\t"; cout <<( end - start ).asSeconds() << " s \n"; } };
World * world;
#endif #endif
|
|
« 1 » 2 3 |