tBane Temat założony przez niniejszego użytkownika |
[SFML 2.X] Renderowanie Terenu i Wody dziedziczących po sf::Drawable, sf::Transformable » 2024-11-02 18:50:18 Witam. Mam obiekty typu Chunk, które zawierają Terrain* terrain oraz Water* water. Obiekty te dziedziczą po sf::Drawable oraz sf::Transformable w celu renderowania sf::Vertex'ów. Terrain* terrain zawiera tablice std::vector < short > tiles, która określa wartości kafelków. W Water* water jest nieco inaczej, a mianowicie zawiera tablicę std::vector < bool > waters, która określa czy na danym polu jest woda. Teraz mam taki problem, że chciałbym na kafelkach z Terrain* terrain renderować shader wody, gdy waters[] == trueJak na razie jedyne co wymyśliłem, to to, że Water by zawierało zdublowane wartości z Terrain w postaci tablicy, ale nie wiem czy to optymalne rozwiązanie.. class Terrain : public sf::Drawable , public sf::Transformable { public: short width, height; sf::Vector2i coords; sf::VertexArray vertexes; Texture * tileset; std::vector < short > tiles; Terrain( short x, short y, short width, short height ) { coords.x = x; coords.y = y; this->width = width; this->height = height; tileset = getTexture( "tiles/0_tileset" ); vertexes.setPrimitiveType( sf::Triangles ); vertexes.resize( width * height * 6 ); tiles.resize( width * height ); short coord_x, coord_y; for( short y = 0; y < height; y++ ) for( short x = 0; x < width; x++ ) { sf::Vertex * triangles = & vertexes[( y * width + x ) * 6 ]; coord_x =( coords.x + x ); coord_y =( coords.y + 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 ); edit( x, y, 2 ); } } private: virtual void draw( sf::RenderTarget & target, sf::RenderStates states ) const { states.transform *= getTransform(); states.texture = & * tileset->texture; target.draw( vertexes, states ); } };
class Water : public sf::Drawable , public sf::Transformable { public: int width, height; sf::Vector2i coords; sf::VertexArray vertexes; Texture * noiseTexture; Shader * shader; std::vector < std::vector < bool > > waters; Water( int x, int y, int width, int height ) { coords.x = x; coords.y = y; this->width = width; this->height = height; waters.resize( height ); for( auto & water: waters ) water.resize( width ); for( int y = 0; y < height; y++ ) for( int x = 0; x < width; x++ ) { waters[ y ][ x ] = false; } noiseTexture = getTexture( "empty" ); shader = getShader( "shaders/lake" ); } private: virtual void draw( sf::RenderTarget & target, sf::RenderStates states ) const { states.transform *= getTransform(); states.texture = &( * noiseTexture->texture ); states.shader = &( * getShader( "shaders/lake" )->shader ); target.draw( vertexes, states ); } };
|
|
pekfos |
» 2024-11-02 21:51:13 Po co w ogóle podział na Terrain i Water? Mapa to mapa. Mnożeniem bytów tylko generujesz problemy, jak ten który opisujesz. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-11-02 21:56:38 Bo tak zrobiłem. Nie wiedziałem jak to inaczej zrobić. Chciałem rozdzielić generowanie terenu od wody gdyż woda ma shader. Poza tym i tak dla każdego typu podłoża muszę wygenerować inne sf::Vertex'es
Teraz planowałem tak podzielić tereny i wody: -Terrain* terrain; (without shader) -Water* lake; (with shader) -Water* ocean; (with shader) -Water* swamp; (with shader) |
|
pekfos |
» 2024-11-02 22:15:08 Zrób to w jednej klasie. Podziel kod jak jego rozmiar lub stopień skomplikowania będzie problemem. Teraz masz problem by to w ogóle rozpisać na wiele klas. Keep it simple, stupid. Poza tym i tak dla każdego typu podłoża muszę wygenerować inne sf::Vertex'es Ja zawsze generowałem VertexArray tymczasowo przy każdym wykonaniu renderowania i to nigdy nie był problem. Nie musisz tego przechowywać. Tym bardziej nie musisz robić nowych klas tylko po to by to przechowywać. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-11-02 22:51:43 Dobra. Zrobiłem tak dla wody. #ifndef Water_hpp #define Water_hpp
class WaterPrefab : public GameObject { public: short id; TerrainPrefab * terrain; Texture * texture; Shader * shader; WaterPrefab( string name, short id, TerrainPrefab * terrain ) : GameObject( name ) { type = GameObjectType::Water; this->terrain = terrain; this->id = id; if( terrain != nullptr ) texture = terrain->texture; shader = getShader( "shaders/" + name ); collider->shape->setPosition( position ); } virtual ~WaterPrefab() { } virtual void update( float dt ) { sf::Vector2f position; position.x = int( worldMousePosition.x ) / int( tileSide ) * int( tileSide ); position.y = int( worldMousePosition.y ) / int( tileSide ) * int( tileSide ); } virtual void draw() { window->draw( * collider->shape ); } };
class Water : public sf::Drawable , public sf::Transformable { public: int width, height; sf::Vector2i coords; sf::VertexArray vertexes; std::vector < short > waters; Water( int x, int y, int width, int height ) { coords.x = x; coords.y = y; this->width = width; this->height = height; waters.resize( width * height ); } void edit( int x, int y, short value = - 1 ) { waters[ y * width + x ] = value; } void edit( sf::Vector2f worldMousePosition, short value = - 1 ) { short coord_x =( worldMousePosition.x - coords.x * 16 ) / 16; short coord_y =( worldMousePosition.y - coords.y * 16 ) / 16; if( coord_x < 0 || coord_x >= width || coord_y < 0 || coord_y >= height ) return; waters[ coord_y * width + coord_x ] = value; } void update() { vertexes.clear(); vertexes.setPrimitiveType( sf::Triangles ); for( int y = 0; y < height; y++ ) for( int x = 0; x < width; x++ ) { if( waters[ y * width + x ] > - 1 ) { sf::Vertex tile[ 6 ]; int coord_x =( coords.x + x ); int coord_y =( coords.y + y ); tile[ 0 ].position = sf::Vector2f( coord_x * tileSide, coord_y * tileSide ); tile[ 1 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide ); tile[ 2 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide ); tile[ 3 ].position = sf::Vector2f( coord_x * tileSide,( coord_y + 1 ) * tileSide ); tile[ 4 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide, coord_y * tileSide ); tile[ 5 ].position = sf::Vector2f(( coord_x + 1 ) * tileSide,( coord_y + 1 ) * tileSide ); short tu =( short( coord_x * tileSide ) % 64 ) +(( waters[ y * width + x ] ) * 64 ); short tv =( short( coord_y * tileSide ) % 64 ); tile[ 0 ].texCoords = sf::Vector2f( tu, tv ); tile[ 1 ].texCoords = sf::Vector2f( tu + tileSide, tv ); tile[ 2 ].texCoords = sf::Vector2f( tu, tv + tileSide ); tile[ 3 ].texCoords = sf::Vector2f( tu, tv + tileSide ); tile[ 4 ].texCoords = sf::Vector2f( tu + tileSide, tv ); tile[ 5 ].texCoords = sf::Vector2f( tu + tileSide, tv + tileSide ); for( int i = 0; i < 6; i++ ) vertexes.append( tile[ i ] ); } } } private: virtual void draw( sf::RenderTarget & target, sf::RenderStates states ) const { states.transform *= getTransform(); states.texture = &( * getTexture( "tiles/0_tileset" )->texture ); states.shader = &( * getShader( "shaders/lake" )->shader ); target.draw( vertexes, states ); } };
#endif
|
|
pekfos |
» 2024-11-02 23:01:02 Mi wtedy zacina grę :-/ To coś musiałeś robić źle. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-11-02 23:02:33 Zapewne tak. Nie jestem tak dobry w programowaniu jak Ty :-) Ostatecznie działa i mam ładne kafelki przejściowe woda-plaża |
|
« 1 » |