Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 2.X] Renderowanie Terenu i Wody dziedziczących po sf::Drawable, sf::Transformable

Ostatnio zmodyfikowano 2024-11-02 23:02
Autor Wiadomość
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[] == true

Jak 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..

C/C++
class Terrain
    : public sf::Drawable
    , public sf::Transformable
{
public:
   
short width, height; // normal is a 16x16
   
sf::Vector2i coords; // multiply by 16x16
   
sf::VertexArray vertexes; // vertexes of tiles
   
Texture * tileset; // main texture
   
std::vector < short > tiles; // tile values
   
   
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 ); // widthMap * heightMap * TwoTrianglesVertices
       
       
tiles.resize( width * height );
       
       
short coord_x, coord_y;
       
       
// TERRAIN - GRASS
       
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
   
{
       
       
// draw tiles - terrain
       
states.transform *= getTransform();
       
states.texture = & * tileset->texture; // TO-DO
       
target.draw( vertexes, states );
   
}
}
;

C/C++
class Water
    : public sf::Drawable
    , public sf::Transformable
{
public:
   
int width, height; // normal is a 16x16
   
sf::Vector2i coords; // multiply by 16x16
   
sf::VertexArray vertexes; // vertexes of water
   
Texture * noiseTexture; // noise texture
   
Shader * shader;
   
std::vector < std::vector < bool > > waters; // TO-DO - to delete
   
   
Water( int x, int y, int width, int height ) {
       
       
coords.x = x;
       
coords.y = y;
       
       
this->width = width;
       
this->height = height;
       
       
// resize the array of water
       
waters.resize( height );
       
for( auto & water: waters )
           
 water.resize( width );
       
       
// all the water is false
       
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 );
       
       
   
}
   
}
;
P-181802
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.
P-181803
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)
P-181804
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ć.
P-181805
tBane
Temat założony przez niniejszego użytkownika
» 2024-11-02 22:51:43
Dobra. Zrobiłem tak dla wody.

C/C++
#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; // normal is a 16x16
   
sf::Vector2i coords; // multiply by 16x16
   
sf::VertexArray vertexes; // vertexes of water
   
std::vector < short > waters; // TO-DO - to make all
   
   
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
P-181806
pekfos
» 2024-11-02 23:01:02
Mi wtedy zacina grę :-/
To coś musiałeś robić źle.
P-181807
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

P-181808
« 1 »
  Strona 1 z 1