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

[SFML 2.0] Bilard (kilka pytań)

Ostatnio zmodyfikowano 2013-07-25 00:49
Autor Wiadomość
johny
Temat założony przez niniejszego użytkownika
[SFML 2.0] Bilard (kilka pytań)
» 2013-07-23 20:20:43
Witam. Piszę grę w bilard i korzystam z SFML i mam parę pytań, niekoniecznie związanych z samą biblioteką.
Napisałem na razie zderzenia bili z bandą, bili z bilą nieruchomą oraz 2 bil w ruchu. Nie uwzględniam jak na razie rotacji bocznych ani postępowych oraz odkształcania się band.

1. Ma ktoś pomysł na jakąś ładną funkcję gaszącą prędkość bili? Tak żeby bila ładnie wyhamowywała do zera?
Bo aktualnie w każdej iteracji pętli zmniejszam prędkość dla każdej bili na stole, o stałą wartość. W rezultacie dostaję efekt nagłego zastopowania (przy niskiej prędkości). A jeśli mnożę prędkość przez stałą wartość (np. 0.9) w każdym kroku, to z kolei nienaturalnie długo wyhamowuje pod koniec.

2. Jeśli w 1 iteracji pętli mam 2 kolizje dla tej samej bili (np. biała uderza w 2 zlepione bile, w obie jednocześnie), to w jaki sposób rozpatrywać takie zderzenia? Żeby to było w pierwszym przybliżeniu dość realistyczne.
Chodzi o taką sytuację:
http://www.youtube.com/watch​?v=YpG6KswfEVQ&feature=youtu.be

Biała chyba nie tak powinna się zachować po takim zderzeniu... ;d Generalnie w tej chwili najpierw jest obsługiwana kolizja dla czerwonej, a następnie dla niebieskiej. Nie potrafię pojąć jak powinny się zachować bile gdy uderzenie następuje jednocześnie.

3. W jaki sposób można wygładzić bile, żeby nie były takie pixelowate? Używam sf::Texture::setSmooth(true), ale to i tak nie dużo daje. Tekstury bile robione w gimpie jako zwykłe koło.

4. Jak ma ktoś jakieś uwagi ciekawe, to oczywiście również proszę!

Jeśli ktoś ma jakiekolwiek doświadczenie albo pomysły z tego typu przypadkami proszę o pomoc:P

P.S. Jak tu się linki dodaje?
P-88638
pekfos
» 2013-07-23 21:07:07
A jeśli mnożę prędkość przez stałą wartość (np. 0.9) w każdym kroku, to z kolei nienaturalnie długo wyhamowuje pod koniec.
Więc wyzeruj prędkość, gdy spadnie poniżej jakiejś wartości.

3. W jaki sposób można wygładzić bile, żeby nie były takie pixelowate?
To zależy od wielu rzeczy. Rozdzielczości, skalowania, jakości tekstury, AA, itp..
P-88643
johny
Temat założony przez niniejszego użytkownika
» 2013-07-23 21:23:44
@pekfos No racja co do tego zerowania. Ale i tak wykres takiej funkcji nie wygląda za ciekawie. Szybki spadek prędkości na początku i powolny pod koniec. Po prostu jak się patrzy na ruch takiej bili to widać, że coś jest nie tak :P



Co do wygładzania, to wczytywana textura ma 256x256. Skaluje ją różnie, w zależności od wyboru rozmiaru okna gry i ustawień. Docelowo bywa 12x12, ale bywa też 40x40 jak eksperymentuję. Czy rozmycie obrazka bili (256x256) w gimpie pomogło by coś?

Fragment kodu ze skalowaniem:
C/C++
//txt_bila to textura
//spr_bila to sprite

if( !txt_biala.loadFromFile( "biala.gif" ) )
     std::cout << "Nie udalo sie wczytac obrazka";

txt_biala.setSmooth( true ); //tutaj smooth

spr_bila.setScale( stol.get_skala() / stol.get_skala_bili(), stol.get_skala() / stol.get_skala_bili() ); //tutaj scale
spr_bila.setOrigin( txt_biala.getSize().x / 2, txt_biala.getSize().y / 2 );
spr_bila.setPosition( x, y );
spr_bila.setTexture( txt_biala );
Niestety ale setScale nie działa na sf::Texture, dlatego muszę skalować sf::Sprite.
P-88646
Mrovqa
» 2013-07-24 14:28:07
Kiedyś też pisałem bilarda, głównie po to, by napisać coś w Box2D (mój kod poniżej). Ogólnie koncepcja wyhamowywania bil polega na tym, że dzielisz sobie przedział możliwych prędkości na kilka podprzedziałów i im wolniej bila się porusza, tym gwałtowniej ją hamujesz. Warto w najniższym przedziale ustawić to prędkość=0.
C/C++
for( b2Body * b = world->GetBodyList(); b; b = b->GetNext() )
{
    if( b->GetType() != b2_dynamicBody ) continue;
   
    ballsCount++;
    b2Vec2 v = b->GetLinearVelocity();
    float vel = b2Sqrt( v.x * v.x + v.y * v.y );
    float force = 0;
    if( vel > 1.f && vel < 5.f ) // v € (1;5)  -- ball diameter 0.5m
    {
        // negative value --- reverse vector return
        force = - b->GetMass() * vel * 20 / hz; // f=mv/t
    }
    else if( vel < 0.1f )
    {
        b->SetLinearVelocity( b2Vec2( 0, 0 ) );
        b->SetAngularVelocity( 0 );
    }
    else // v € [0.1;1]
    {
        // negative value --- reverse vector return
        force = - b->GetMass() * vel * 100 / hz; // f=mv/t
    }
   
    if( force ) // applying some force
    {
        float32 sinv = v.y / vel;
        float32 dy = sinv * force;
        float32 dx = b2Sqrt( force * force - dy * dy ) * sgn( force * v.x );
       
        b->ApplyForceToCenter( b2Vec2( dx, dy ) );
    }
}
Możesz też prędkość wyliczać na podstawie konkretnej części konkretnego wykresu, np. przedział [0..1] tego wykresu: http://www.wolframalpha.com​/input/?i=1-x%5E3
Gdzie oś Y to prędkość, a oś X to czas, który minął - oczywiście wszystko odpowiednio skalując, by otrzymać zamierzony efekt. Od razu dodam, iż nie testowałem tego sposobu, ale to kwestia dobrania odpowiedniego wzoru i późniejszych lekkich korekt.

PS napisałem o tym, bo na filmiku nie najlepiej wyhamowywałeś bile ;)
P-88665
johny
Temat założony przez niniejszego użytkownika
» 2013-07-24 21:03:08
Dzięki! Właśnie o takie coś mi chodziło. A co do wykresu, to jeśli bym wiedział jaki powinien być jego kształt, to właśnie bym wygenerował sobie jakąś LUT i na jej podstawie hamował.

Aktualnie mam jeszcze inny problem, który pojawił się wczoraj wieczorem, przy pierwszym rozbijaniu trójkąta (ustawienia początkowego). Jeśli jest zbyt dużo bil to dzieją się głupoty i kolizje działają źle.

Generalnie jak powinno wyglądać sprawdzanie kolizji w takim bilardzie? Przesuń o wektor prędkości -> sprawdź czy nie ma kolizji -> obsłuż kolizję -> zaktualizuj położenie -> rysuj scenę ? Przy takim scenariuszu dokładność wzrasta wraz z częstotliwością sprawdzania, przy proporcjonalnie mniejszej prędkości (bo lepiej sprawdzać co 1 pixel czy nie ma kolizji, niż co 5).

Ale im gęściej sprawdzam, tym bardziej katuje procesor, a chyba nie o to chodzi. Bo przecież można sprawdzać co 0.1 pixela położenie...
P-88705
Mrovqa
» 2013-07-25 00:49:37
Jeśli chodzi o kolizje to masz wybór: mniej dokładne i mniejsze wykorzystanie procesora albo dokładniejsze i większe wykorzystanie procesora (logiczne, nie? ;)). Po prostu musisz znaleźć "złoty środek" i pozostawić to, co Ci odpowiada. Jaki dokładny algorytm zastosować to no niestety nic tu nie polecę (osobiście pewnie bym coś wygooglał, ostatecznie wykorzystał w miarę prosty algorytm, który bym wymyślił), ale zawsze możesz popatrzeć w źródła Box2D tudzież innej biblioteki.
P-88724
« 1 »
  Strona 1 z 1