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

[SFML] View - stałe tło + renderowanie tylko spriteów które są widoczne w View.

Ostatnio zmodyfikowano 2014-03-16 22:19
Autor Wiadomość
OczkoSX
Temat założony przez niniejszego użytkownika
[SFML] View - stałe tło + renderowanie tylko spriteów które są widoczne w View.
» 2014-03-16 09:26:19
Witam! Na początku może zapodam kod:
mapy.h
C/C++
// mapy.h - Klasa CMapa

#ifndef mapy_h
#define mapy_h

#include "fzi.h"
#include "bloki.h"

class CMapa // Klasa mapa
{
private: // Skladniki prywatne
    int wybr_mapa = 0; // Wybrana mapa
    int ilosc_map; // Ilosc zaladowanych map
    int wys, szer; // Wys i szer mapy kafelkowej
    string nazwa; // Nazwa mapy
    short int ** mapa_tab; // Deklaruje tablice
   
public: // Skladniki publiczne
   
    void stw_tablice() // Funkcja odpowiedzialna za stworzenie tablicy mapy kafelkowej
    {
        {
            mapa_tab = new short int *[ wys ];
            for( int i = 0; i < wys; i++ )
            {
                mapa_tab[ i ] = new short int[ szer ];
            }
        }
    }
   
    void zaladuj_tablice() // Wypisywanie kafelek do tablicy
    {
        stringstream sciezka;
        sciezka << "maps\\mapa" << wybr_mapa << ".dat";
        fstream mapa_file( sciezka.str() ); // Wczytanie pliku
        if( !mapa_file.good() ) exit( 0 );
       
        getline( mapa_file, nazwa ); // Wczytanie nazwy mapy
       
        mapa_file >> wys >> szer; // Wczytanie wys i szer
       
        stw_tablice(); // Tworzy tablice
       
        for( int i = 0; i < wys; i++ ) // Wypelnia tablice mapa kafelkowa
        {
            for( int j = 0; j < szer; j++ )
            {
                mapa_file >> mapa_tab[ i ][ j ];
            }
        }
       
        mapa_file.close(); // Zamyka strumien
    }
   
    void liczba_map() // Wczytywanie ilosci map i wpisywanie do zmiennej
    {
        while( true )
        {
            stringstream sciezka;
            sciezka.str( "" );
            sciezka << "maps\\mapa" << ilosc_map << ".dat";
            ifstream exist( sciezka.str().c_str() );
            if( exist.good() ) ilosc_map++;
            else break;
           
        }
    }
   
    void rys_mape() // Rysowanie mapy
    {
        for( int i = 0; i < wys; i++ ) // Petla - wysokosc mapy
        {
            for( int j = 0; j < bloki.ilosc_blokow; j++ ) // Petla - ustawianie pozycji blokow
            {
                bloki.blok[ j ].setPosition( 0, i *( bloki.blok[ j ].getGlobalBounds().height ) );
            }
           
            for( int j = 0; j < szer; j++ ) // Petla - szerokosc mapy
            {
                if( mapa_kaf.mapa_tab[ i ][ j ] != - 1 ) APP.draw( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ] ); // Wypisz blok jesli nie jest on powietrzem
               
                for( int k = 0; k < bloki.ilosc_blokow; k++ ) // Petla - porusz blokami na kolejna pozycje
                {
                    bloki.blok[ k ].move( bloki.blok[ k ].getGlobalBounds().height, 0 );
                }
            }
        }
    }
   
} mapa_kaf; // Deklaracja obiektu mapa_kaf klasy CMapa

#endif

bloki.h
C/C++
// bloki.h - Tworzenie blokow (sprite)

#ifndef bloki_h
#define bloki_h

#include "fzi.h"

class CBloki // Klasa CBloki
{
private: // Skladniki prywatne
    friend class CMapa; // Zaprzyjazniona klasa
    int blok_szer = 50, blok_wys = 50; // Szerokosc i wysokosc bloku
    static const int ilosc_blokow = 2; // Ilosc blokow zaprogramowanych w programie
    sf::Texture blok_tex[ ilosc_blokow ]; // Textura sprite
    sf::Sprite blok[ ilosc_blokow ]; // Bloki jako Sprite'y
public: // Skladniki publiczne
    void bloki() // Funkcja od tworzenia sprite'ow
    {
        for( int i = 0; i < ilosc_blokow; i++ )
        {
            ostringstream sciezka;
            sciezka.str( "" );
            sciezka << "bloki\\blok" << i << ".png";
            if( !blok_tex[ i ].loadFromFile( sciezka.str() ) ) exit( 0 );
           
            blok[ i ].setTexture( blok_tex[ i ] );
            blok[ i ].setScale( blok_szer / blok[ i ].getGlobalBounds().width, blok_wys / blok[ i ].getGlobalBounds().height );
        }
    }
} bloki;

#endif bloki_h

fzi.h
C/C++
// fzi.h - Funkcje, zmienne i biblioteki

#ifndef fzi_h
#define fzi_h

using namespace std;

#include <SFMl/Graphics.hpp>
#include <fstream>
#include <string>
#include <sstream>

extern sf::RenderWindow APP;

#endif

main.cpp
C/C++
#include "fzi.h"
#include "bloki.h"
#include "mapy.h"

sf::RenderWindow APP;

int main()
{
    APP.create( sf::VideoMode( 1600, 900, 32 ), "Okno Aplikacji" );
    bloki.bloki();
    mapa_kaf.liczba_map();
    mapa_kaf.zaladuj_tablice();
   
    while( APP.isOpen() )
    {
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Escape ) ) APP.close();
       
        mapa_kaf.rys_mape();
        APP.display();
        APP.clear();
    }
}


Jest to kod wszystkiego co na razie napisałem. Program wczytuje mape z pliku, odpowiednie textury i wyświetla je na ekranie (zaczątki gry :D). Chciałbym dodać View i mam odnośnie co do tego kilka pytań:

1. Czy jak będe rysował sprite wielkosci ekranu (tło) w View, to czy będzie cały czas statyczne i nie będzie się przemieszczało razem z innymi obiektami?
2. Możecie podsunąć pomysł jak przerobić metodę CMapa::rys_mape() aby rysowała tylko to co widzi użytkownik? (za pomocą View)

PS. W SFML'u siedzę dopiero tydzień więc nie bijcie jeśli coś nie tak z kodem :D Jeśli macie jakieś zastrzeżenia co do kodu to piszcie (jest to mój pierwszy program napisany obiektowo w oparciu o klasy)
P-106512
Pokropow
» 2014-03-16 09:58:35
Jeżeli chcesz zrobić tło które nie porusza się względem kamery to w pętli głównej zmieniaj pozycje Sprajta-Tła na pozycję View
np:
C/C++
Sprite sprajt_tlo;
sprajt_tlo.setCenter( ustawienie srodka tla );
View kamera;
while( petlaGlowna )
{
   
    sprajt_tlo.setPosition( kamera.getCenter() );
}
P-106517
OczkoSX
Temat założony przez niniejszego użytkownika
» 2014-03-16 10:07:02
Dzięki wielkie! A powiedz mi, wyjdzie to samo jeśli zrobię to tak (piszę obecnie z głowy)?
C/C++
APP.setView( widok );
//rysowanie sprite

PS. To jest moje pierwsze spotkanie z widokami, myślałem nad tym sposobem, gdyż z tego co mi wiadomo to każdy obiekt rysowany po ustawieniu widoku stosuje się do niego. Czyli jak narysuje sprite, to będzie on tam gdzie view. Mam rację? Czy może i tak trzeba ustawić jego pozycję?
P-106518
Pokropow
» 2014-03-16 10:16:47
Ale jak później przesuniesz widok, to sprajt chyba zostanie tam gdzie był. Tak mi się przynajmniej wydaje. Najlepszym sposobem byłoby po prostu wstawienie tego do kodu i sprawdzenie czy działa.
P-106519
Pokropow
» 2014-03-16 10:27:59
A co do drugiego pytania rozwiązła bym to funkcją która sprawdza czy sprajt jest w polu widzenia kamery i rysował tylko jeżeli zwróci true

Funkcja:
C/C++
int czy_w_polu_View( sf::Sprite & sprajt, sf::View & view )
{
    Vector2f pos = Vector2f( view.getCenter().x - view.getSize().x / 2, view.getCenter().y - view.getSize().y / 2 ); /** pozycja lewego gornego rogu kamery */
    Vector2f spriteSize = Vector2f( sprajt.getGlobalBounds().width, sprajt.getGlobalBounds().height );
   
    if( sprajt.getPosition().x + spriteSize.x < pos.x ) /** Objekt jest po lewej stronie kamery*/
         return 0;
   
    if( sprajt.getPosition().x > pos.x + view.getSize().x ) /** Objekt jest po prawej stronie kamery*/
         return 0;
   
    if( sprajt.getPosition().y + spriteSize.y < pos.y ) /** Objekt jest nad kamerą*/
         return 0;
   
    if( sprajt.getPosition().y > pos.y + view.getSize().y ) /** Objekt jest pod kamerą*/
         return 0;
   
    return 1;
   
   
}
w metodzie rysującej:
C/C++
if( czy_w_polu_View( sprajt, widok ) )
     draw( sprajt );


Funkcja działa tylko jeżeli środek sprajta jest ustawiony na lewy górny róg (0,0) czyli domyślnie

Trochę zmodyfikowałem bo zauważyłem błąd. Jak zapewne zauważyłeś ta funkcja działa podobnie do wykrywania kolizji. 
P-106520
OczkoSX
Temat założony przez niniejszego użytkownika
» 2014-03-16 10:51:31
Hym, z tego co mi wiadomo jest też metoda .contains. Myślisz że zadziała jak zrobię:
if( polozenie + rozmiar widoku.contains( polozenie + rozmiar sprite ) )
?

Dobra, pokombinuję i jeśli coś nie wyjdzie to się zgłoszę do was :D
P-106521
OczkoSX
Temat założony przez niniejszego użytkownika
» 2014-03-16 11:29:18
Jakbym tego nie zrobił to nie działa... Łapcie kod:
C/C++
#include "fzi.h"
#include "bloki.h"
#include "mapy.h"

sf::RenderWindow APP;
sf::RectangleShape hero;
sf::View view;
void postac();
void widok();

int main()
{
    APP.create( sf::VideoMode( 1600, 900, 32 ), "Okno Aplikacji" );
    bloki.bloki();
    mapa_kaf.liczba_map();
    mapa_kaf.zaladuj_tablice();
    postac();
   
    sf::Texture bg_txt;
    bg_txt.loadFromFile( "bg.png" );
    sf::Sprite bg( bg_txt );
    bg.setScale( APP.getSize().x / bg.getGlobalBounds().width, APP.getSize().y / bg.getGlobalBounds().height );
    bg.setOrigin( sf::Vector2f( bg.getGlobalBounds().width / 2, bg.getGlobalBounds().height / 2 ) );
   
    while( APP.isOpen() )
    {
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::D ) ) hero.move( 1, 0 );
       
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::A ) ) hero.move( - 1, 0 );
       
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::W ) ) hero.move( 0, - 1 );
       
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::S ) ) hero.move( 0, 1 );
       
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Escape ) ) APP.close();
       
        widok();
        bg.setPosition( sf::Vector2f( view.getCenter() ) );
        APP.draw( bg );
        mapa_kaf.rys_mape();
        APP.draw( hero );
        APP.display();
        APP.clear();
    }
}

void postac()
{
    hero.setSize( sf::Vector2f( 50, 50 ) );
    hero.setFillColor( sf::Color::Red );
}

void widok()
{
    view.setSize( sf::Vector2f( APP.getSize() ) );
    view.setCenter( sf::Vector2f( hero.getPosition().x +( hero.getGlobalBounds().width / 2 ), hero.getPosition().y +( hero.getGlobalBounds().height / 2 ) ) );
    APP.setView( view );
}

Zrobiłem ładnie że w gracz jest w centrum, ale nie mogę ustawić tej nieszczęsnej tapety... Oto rezultat:

http://screenshooter.net​/4771684/odeoang

EDIT: OK, poradziłem sobie. Wystarczyło dac setOrigin przed SCALE. PS. Sory za double post :<
PS. Zostało mi jeszcze renderowanie tych obiektów...
P-106524
OczkoSX
Temat założony przez niniejszego użytkownika
» 2014-03-16 13:07:47
C/C++
void rys_mape() // Rysowanie mapy
{
    for( int i = 0; i < wys; i++ ) // Petla - wysokosc mapy
    {
        for( int j = 0; j < bloki.ilosc_blokow; j++ ) // Petla - ustawianie pozycji blokow
        {
            bloki.blok[ j ].setPosition( 0, i *( bloki.blok[ j ].getGlobalBounds().height ) );
        }
       
        for( int j = 0; j < szer; j++ ) // Petla - szerokosc mapy
        {
            if( czy_w_polu_View( i, j ) )
            {
                if( mapa_kaf.mapa_tab[ i ][ j ] != - 1 ) APP.draw( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ] ); // Wypisz blok jesli nie jest on powietrzem
               
            }
           
            for( int k = 0; k < bloki.ilosc_blokow; k++ ) // Petla - porusz blokami na kolejna pozycje
            {
                bloki.blok[ k ].move( bloki.blok[ k ].getGlobalBounds().height, 0 );
            }
        }
    }
}

int czy_w_polu_View( int & i, int & j )
{
    sf::Vector2f pos = sf::Vector2f( view.getCenter().x - view.getSize().x / 2, view.getCenter().y - view.getSize().y / 2 ); /** pozycja lewego gornego rogu kamery */
    sf::Vector2f spriteSize = sf::Vector2f( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getGlobalBounds().width, bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getGlobalBounds().height );
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().x + spriteSize.x < pos.x ) /** Objekt jest po lewej stronie kamery*/
         return 0;
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().x > pos.x + view.getSize().x ) /** Objekt jest po prawej stronie kamery*/
         return 0;
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().y + spriteSize.y < pos.y ) /** Objekt jest nad kamerą*/
         return 0;
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().y > pos.y + view.getSize().y ) /** Objekt jest pod kamerą*/
         return 0;
   
    return 1;
}

Moja funkcja rysująca. nie zauważyłem jakichkolwiek zmian wydajnosciowych... nadal około 675fps. może coś skopalem? 400 kafelek. w domu jak będę zrobię więcej

//EDIT

Przepisałem na nowo funkcję. Teraz jest ponad 2 razy mniejsza :D

C/C++
void rys_mape() // Rysowanie mapy
{
    for( int i = 0; i < wys; i++ ) // Petla - wysokosc mapy
    {
        for( int j = 0; j < szer; j++ ) // Petla - szerokosc mapy
        {
            bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].setPosition( sf::Vector2f( j * bloki.blok_szer, i * bloki.blok_wys ) );
            if( mapa_kaf.mapa_tab[ i ][ j ] != - 1 && czy_w_polu_View( i, j ) ) APP.draw( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ] );
           
        }
    }
}

int czy_w_polu_View( int & i, int & j )
{
    sf::Vector2f pos = sf::Vector2f( view.getCenter().x - view.getSize().x / 2, view.getCenter().y - view.getSize().y / 2 ); /** pozycja lewego gornego rogu kamery */
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().x + bloki.blok_szer < pos.x ) /** Objekt jest po lewej stronie kamery*/
         return 0;
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().x > pos.x + view.getSize().x ) /** Objekt jest po prawej stronie kamery*/
         return 0;
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().y + bloki.blok_wys < pos.y ) /** Objekt jest nad kamerą*/
         return 0;
   
    if( bloki.blok[ mapa_kaf.mapa_tab[ i ][ j ] ].getPosition().y > pos.y + view.getSize().y ) /** Objekt jest pod kamerą*/
         return 0;
   
    return 1;
}

Idę zaraz zrobić na szybko programik, który będzie wybranym klockiem uzupełniać obszar o podanych wymiarach (tymczasowo dla testów wydajności).

EDIT 2: Jest różnica D:
Na mapie 100x100 wypełnionej jednym obiektem normalnie jest 180fps, a gdy renderuje się tylko obszar który jest widoczny prawie 500! (na trybie debug :D)
Na mapie wielkości miliona kafelek (1000x1000) normalnie są 1 - 2fps'y, a przy opcji z view 9... I tu się trochę zdziwiłem. Wpadłem na pomysł, że przecież musi dla miliona kafelek sprawdzać czy się znajdują w obszarze View. Postanowiłem, że muszę napisać funkcję, lub przerobić tą, aby więcej nie sprawdzało kiedy jedna wychodzi. Jak ktoś chce pomóc to się nie obraże :D
P-106547
« 1 » 2
  Strona 1 z 2 Następna strona