Witam, Tworze sobie grę dokładnie Minecraft 2D próbuje zastosować tam techniki które użyję w przyszłości do rozwijanego wciąż silniczka na SFML. :) Ale Zmagam się z problemem generowania mapy w locie. Gdyż mapa będzie naprawdę olbrzymia generowana po kluczu SEED. To już zrobiłem ale teraz kwestia kolizji oraz rysowania.
Powiem wam jak to jak na razie u mnie wyglgąda.
Mam dwa kontenery w jednym wszystkie obiekty gry razem w drugim również wszyskie obiekty ale podzielone w quadTree do kolizji, które swoją drogą nie działają najlepiej na granicach jednego drzewka z drugim, ale mniejsza o to. Wiadomo marnotrawienie pamięci ale nic lepszego nie wymyśliłem.
Algorytmem PerlinNoice generuję jakąś wysokość i do wysokości minimalnej dodaję wygenerowaną z klucza wysokość daje to ładny efekt. I fajne mapy się robią
Następnie robię pętlę i,j i dodaję kolejno do obu kontenerów każdy obiekt.
Wygląda to mniej więcej tak:
PerlinNoise * noise = new PerlinNoise( SEED, CHUNK );
p = new Quadtree( 0.0f, 0.0f,(( worldSizeMin.x + worldSizeMax.x ) * 32 ),(( worldSizeMin.y + worldSizeMax.y ) * 32 ), 0, 3 );
float width = 32;
float height = 32;
long long int summator = 0;
for( int i = 0; i < worldSizeMax.x + worldSizeMin.x; i++ ) //columns (x values
{
int columnHeight = 2 + noise->getNoise( i - worldSizeMin.x, worldSizeMax.y - worldSizeMin.y - 2 );
mapIndex.push_back( sf::Vector3f( i,( worldSizeMin.y + columnHeight ), summator ) );
summator = summator + worldSizeMin.y + columnHeight;
for( int j = 0; j < worldSizeMin.y + columnHeight; j++ ) //rows (y values)
{
sf::Vector2f currentPosition( i * width,(( worldSizeMax.y + worldSizeMin.y ) - j ) * height );
DirtGrass * dirtGrass = new DirtGrass( currentPosition, sf::Vector2f( width, height ) );
p->AddObject( dirtGrass );
worldContainer.push_back( dirtGrass );
}
}
Jak widać mam jeszcze kontener o nazwie mapIndex dzięki któremu mogę sobie ograniczyć generowany obszar do rysowania:
Jak widać summator dodawany do mapIndex to ilość klocków które znajdują się przed elementem. jak dla x=0 tworzymy 7 klocków to dla x=1 sumator=7 ... a jeśli w x1 zrobimy już 10 kolejnych klocków to dla x2 sumator = 17 i tak dalej. tak więc wiemy że jak mamy rysować od np x1 do x10 to robimy zwykłą petlę w której od i=0 dodajemy summator gdyż wiadomo, że w kontenerze od i = 7 są już klocki z x1 (przynajmniej zakładamy że od 7 aż do końca wysokości zapisanej w mapIndex będą klocki z pozycją odpowiadającą x1).
Rysowanie wygląda jak na razie tak:
for( int i = cam.mX /* Okreslana wielkość ekranu względem kamery, gracz na pozycji np 1024 to wiadomo że trzeba rysować dla x=32 bo jeden klocek ma 32 px czyli 32*32 to 1024 */; i < cam.screenSizeX + cam.mX /* do początku dodajemy rozdzielczość ekranu dzielona przez 32 czyli jeden klocek*/; i++ )
{
for( long long int j = abs( cam.mY ) - int( cam.screenSizeY ); j < abs( cam.mY ) + int( cam.screenSizeY ) / 2; j++ ) // Robimy to samo co wyżej ale określamy wartość rysowania w pionie.
{
WindowApp->draw( w1->cont[ w1->mapIndex[ i ].z + j ]->drawableObject );
}
}
Mam nadzieję że kod jest dość jasny i że da się go ogarnąć. Tylko takie rozwiązanie ma jednak wadę. Jak będziemy chcieli usunąć albo dodać jakiś klocek to będziemy musieli znaleźć go w mapIndex i potem dla każdego x zmniejszyć wartość summatora o jeden gdyż liczba klocków zmniejszyła się.
O usuwaniu z quadTree i z vektora przechowującego wszystkie obiekty ze wszystkimi klockami nie wspomnę.
Dodawanie byłoby jeszcze gorsze gdyż trzeba by go dodać w odpowiednim miejscu w kontenerze aby się nie posypało. I zwiększyć każdy summator w przód.
Druga sprawa jak chce mieć "nieskończony" świat to przecież nie mogę wszystkiego trzymać w kontenerze myślałem żeby generować tylko trochę ponad rozdzielczość ekranu i na bieżąco usuwać (jak gracz idzie w prawo) obiekty po lewej i generować nowe po prawej i analogicznie odwrotnie jakby gracz szedł w drugą stronę. i zrobić dodatkowy kontener dla zmian jaki gracz wprowadził czyli np idę w lewo generuję np 10 klocków ale w kontenerze ze zmianami jest zapisane że na pozycji x,y klocek został usunięty więc go pomijam przy generowaniu... Fajna opcja do zapisu gry by to była.
Czy to co napisałem ma jakikolwiek sens?