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

SFML gra przewijana pionowo

Ostatnio zmodyfikowano 2017-10-08 10:56
Autor Wiadomość
latajacaryba
Temat założony przez niniejszego użytkownika
SFML gra przewijana pionowo
» 2017-07-30 00:04:43
Witam. Interesowało by mnie stworzenie kiedyś czegoś podobnego do tego: https://www.youtube.com/watch​?v=csfJaEkZcTo
Autor udostępnia kod, jednak ani nie znam OpenGL ani Gluta, ale nie proszę o jego wyjaśnianie.

1. Jak wczytywać tekstury z czegoś takiego ?
2. Jak stworzyć taką mapę?
3. w jaki sposób to wyświetlać (bo nie wyświetlamy tego, co poza ekranem), choć to już pewnie zależy od implementacji zapisu mapy.
4. w jakiej kolejności to wyświetlać (np. żeby nie było widać gracza schowanego pod drzewem). Pomyślałem, że można to zrobić tak:

Wyświetlanie w następującej kolejności
* trawa, góry, drogi, wode itp.
* mosty, schody i drabiny, kwiaty, kamienie
* gracz i przeciwnicy
* drzewa i inne rzeczy za którymi można się schować

5. Jak sprawdzać kolizje? Nie ma sensu sprawdzać jej np. z fragmentem góry, do którego i tak nie mamy dostępu (bo powiedzmy nie ma schodów). A może nie opłaca się bawić w jakieś rozgraniczanie z czym można kolidować, a z czym nie?

Może są jakieś popularne sposoby na rozwiązanie powyższych problemów?
P-163709
Saran
» 2017-07-30 01:24:14
1. Według mnie musisz po prostu pisać pozycje, nie mam innych pomysłów.
2. Masz na myśli mapę z tych obiektów z (1)? No to tworzysz sobie jakiś edytor do map i już, lub używasz gotowego (Tiled?).
3. To łatwe, sprawdzasz pozycję sf::View względem mapy, lub coś takiego, a potem w pętli wyświetlasz (najłatwiej będzie jeśli to mapa kafelkowa). Patrzysz na pozycję gracza, a potem robisz coś takiego:
a)
C/C++
for( int i = pozycja_gracza_x - rozmiar_widocznej_planszy_x / 2;
i < pozycja_gracza_x + rozmiar_widocznej_planszy_x / 2;
i++ )
{
    for( int j = pozycja_gracza_y - rozmiar_widocznej_planszy_y / 2;
    j < pozycja_gracza_y + rozmiar_widocznej_planszy_y / 2;
    j++ )
    {
        draw( tile[ y ][ x ] );
    }
}

b) Jeśli to nie mapa kafelkowa no to... przed rysowaniem możesz sprawdzać, czy pozycja obiektu znajduje się w zasięgu kamery. Jeśli na przykład kamera obejmuje jednowymiarowy obszar x od 0 do 700, wtedy obiekt mający x = 1400 nie zmieści się. Będzie to nieco wolniejsze, bo musisz iterować po wszystkich obiektach na mapie, zamiast tylko tych znajdujących się w zasięgu kamery.
Powinno dać się to jeszcze zoptymalizować, za pomocą stworzenia trójwymiarowej abstrakcyjnej tablicy kafelków(abstrakcyjnej, bo w tym przykładzie nie mamy kafelków), gdzie przechowywane byłyby id obiektów, które są najbardziej bliskie danemu kafelkowi, a tym samym MOGĄ mieścić się w zasięgu widoczności kamery. Tą trójwymiarową tablicę (a raczej std::vector) obliczamy przed startem gry. Potem tak jak w przykładzie a) lecimy pętlą po tej tablicy, rysując każdy obiekt (id) z pola mieszczącego się na danej pozycji.

4. Dokładnie, twój sposób jest prawidłowy (tak mi się wydaje...). Tylko co jeśli gracz stanie przed drzewem? Wtedy drzewo narysuje się na nim. Jeśli się za nim schowa będzie natomiast tak, jak opisałeś. Możesz rozwiązać ten kłopot za pomocą rysowania najpierw najdalszych obiektów (oś y?), a dopiero później najbliższych, w tym postać. Z zachowaniem hierarchii rysowania, którą opisałeś.

Uff, no to się napisałem, mam nadzieję że pomogłem.
P-163710
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-07-30 02:07:33
Na wstępie dziękuję za odpowiedź

Nie do końca rozumiem działanie pętli, czy mógłbyś wyjaśnić?
Nigdy nie korzystałem z sf::view ale zakładam, że pozycja gracza jest określana względem tego widoku.
Rozumiem, że pętla 'i' wykonuje się aż i mające wartość lewego brzegu mapy będzie miało wartość prawego brzegu mapy. Tylko dlaczego inkrementujemy to co 1 piksel?

Czy nie lepsze byłoby:
C/C++
for( int i = PozGraczaX - SzerMapy / 2; i < PozGraczaX + SzerMapy / 2; i += SzerokoscKafelka )
{
    // kolejna petla to samo tylko dla Y
    {
        draw( Title[ j / WysokoscKafelka ][ i / SzerokoscKafelka ] );
    }
}






PS. Też myślałem nad kafelkową, tylko jak to potem zapisać w pliku tekstowym.
Byłoby łatwo, gdyby wszystkie kafelki miały taki sam rozmiar, bo wtedy zapisujemy po prostu numer tekstury (trawa - 0, droga - 1 itp)
i rysujemy od lewej do prawej, od góry do dołu.
Jednak tu są domki i drzewa. I tu jest pies pogrzebany ;)
P-163711
Saran
» 2017-07-30 02:18:10
Rozumiem, że pętla 'i' wykonuje się aż i mające wartość lewego brzegu mapy będzie miało wartość prawego brzegu mapy. Tylko dlaczego inkrementujemy to co 1 piksel?
W tym przypadku chodziło mi nie o piksele, a o kafelki mapy. Taka mapa składa się przecież z przykładowo 32x32 kafelków, a nie 1024x1024 pixeli (32x32px).
P-163712
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-07-30 02:23:01
W tym przypadku chodziło mi nie o piksele, a o kafelki mapy.
Czyli ta zmodyfikowana i+=SzerKafelki będzie ok.

Dziękuję, to teraz tylko czekać na przypływ chęci... no i muszę to sobie dobrze rozplanować, bo zbyt wiele razy moje ambitne projekty musiałem porzucać, przez zły plan. W każdym razie na pewno z tego skorzystam :)

P-163713
Saran
» 2017-10-08 10:56:25
5. Quadtree - Drzewo czwórkowe.

Jednak tu są domki i drzewa. I tu jest pies pogrzebany ;)
Wystarczy określić rozmiar każdego z tych obiektów - np 3 kratki szerokości i 5 długości, a później wymyślić jakiś format w jakim to zapiszesz w pliku.
Chyba, że obiekty mają rozmiar nieregularny, np:
01110
00100
00100 (drzewo)

Wtedy też się z pewnością da to jakoś zrobić - możesz choćby podzielić te duże obiekty na pojedyncze pola, a później zapisywać je jako osobne ID. Czyli powyższe drzewo składałoby się z 3 rodzajów bloków liści, a także z 2 pni. RPG Maker tak robi, z tego co wiem. I mnóstwo starych strategii.
P-165520
« 1 »
  Strona 1 z 1