Warsztat.GD

Programowanie => Projektowanie kodu => Wątek zaczęty przez: snajper_44 w Październik 30, 2010, 21:47:10

Tytuł: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 21:47:10
Witam! Jestem początkującym programmerem. Piszę sobie pseudo grę w konsoli. Już trochę w miare jest ~500 linijek. Usiłuję zrobić zapis stanu gry, lecz nie wiem jak się do tego zabrać wiem jak odczytać zmienne itp. ale jak powrócić do danego fragmentu kodu? Narazie stworzyłem coś takiego:
void SaveGame(character &Hero)
{
    ofstream osave;
    osave.open("frpg_dbsv", ios::out);
    osave << Hero.name << "\n" << Hero.hp << "\n" << Hero.MinDmg << "\n" << Hero.MaxDmg << "\n" << Hero.lvl << "\n" << Hero.exp << "\n" << Hero.atk;
    osave.close();
};

void LoadGame(character &Hero)
{
    fstream isave("frpg_dbsv", ios::in);
    getline(isave, Hero.name);
    isave.close();
};

int main(int argc, char *argv[])
{
    //blablabla
    cout << "-+-+-+-+-+TRYB+-+-+-+-+-" << endl;
        cout << "Wybierz tryb:" << endl;
        cout << " 1. Nowa gra" << endl;
        cout << " 2. Wczytanie gry" << endl;
        cin >> game;
        if (game == 2)
        {
            LoadGame(Hero);
        }
        if (game == 1)
        //blablabla
        SaveGame(Hero);

Jak widać Hero to obiekt klasy. I moje pytanie jak zrobić właśnie żeby skoczyć po wczytaniu do danego fragmentu? Proszę o pomoc.
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: FoToN w Październik 30, 2010, 21:52:17
Najprościej byłoby otworzyć plik binarnie (std::ios::binary) i wpakować od razu całą klasę. Takie rozwiązanie daje Ci też możliwość łatwego wczytywania. Ważne tylko byś w klasie bohatera nie trzymał np. std::string, tablic, bo wtedy takie rozwiązanie nie zda egzaminu.
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 21:57:03
Ok, lecz to tylko 1/2 odpowiedzi, mi bardziej chodzi oto, że po wywołaniu funkcji LoadGame() załadował by się no nie wiem etykieta? fragmentu kodu i tam by historia była kontunuowana. Zapisać do pliku gdzie jestem to raczej łatwo nawet integerem i dać komenta, że x to gdzieś a y gdzieś.
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Kos w Październik 30, 2010, 22:01:42
Dla gry realtime (well, dla jakiejkolwiek gry z pętlą główną) nie ma potrzeby wracać do tego samego "miejsca w kodzie", bo to się robi samo. Przerywasz grę gdzieś w mainloopie (np. przy eventach), zapisujesz dane, a przy wczytywaniu przywracasz stan gry i odpalasz ponownie pętlę główną - tyle.

A może Twoja gra nie ma pętli głównej i stąd problem?
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Xirdus w Październik 30, 2010, 22:02:07
Tak jak powiedział FoToN, zapisuj binarnie. Ja polecam taki sposób: w pierwszej linii wszystkie inty i podobne, a stringi jeden na linię, na początku każdej linii ze stringiem dajesz inta z rozmiarem.

Plik wyglądałby mniej więcej tak:
[lvl][exp][hp]
[size]Imię bohatera

(za chwilędam przykładowy kod)

A co do zaczynania w miejscu gdzie się skończyło, to po prostu zapisz miejsce, gdzie się skończyło (pole mapy, stage, cokolwiek).
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Kos w Październik 30, 2010, 22:03:11
@Xirdus - ale kolega napisał, że nie chodzi mu o dane, nie powtarzaj Fotona :)
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: FoToN w Październik 30, 2010, 22:07:27
Zapisywanie stanów przykładowo questów możesz zrobić tak:

// Nagłówek pliku
struct NaglowekPliku
{
       (...)
       unsigned int LiczbaQuestow;
       unsigned int OffsetDoPierwszegoQuesta;
       (...)
};

struct Quest
{
      Tutaj id questu, nazwa lub co tam chcesz
      unsigned int EtapQuestu;
};

Opis:
W nagłówku masz liczbę questów i offseta do pierwszego questa. Przesuwasz wskaźnik pobierania na tenże offset i  zaczynasz pobieranie stanu questów. Pobierasz tyle questów, że AktualnyQuest < LiczbaQuestow.
Oczywiście w pliku możesz, a nawet musisz trzymać inne informacje. Robisz to analogicznie do questów.
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 22:18:11
Wiem, że to zabrzmi głupio, ale nie rozumiem Was. Sorry jak powiedziałem moje c++ = 7 dni (wcześniej 3 miechy Pascala) Jak wziąść rozmiar stringa czy o co tam chodziło? Ja pomyślałem tak i mam takie coś: co ileś tam czasu będzie można wybrać zapis tak/nie, tak - zapisz grę (zmienne itp., chapter = 1). Potem w LoadGame() jeżeli chapter == 1 to przejdź do etykiety 'xyz' ale teraz następne pytanie. To będzie ujęte w funkcji Load i Save [Game] a jak odwołać się do etykiety funkcji main()? Przekazać parametry? Czy jak?
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Kos w Październik 30, 2010, 22:21:03
Cytuj
Sorry jak powiedziałem moje c++ = 7 dni (wcześniej 3 miechy Pascala)

To dużo. Powinieneś móc mi odpowiedzieć, jak jest zbudowany control flow w Twojej grze? Bez tego nie poradzimy.
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 22:24:09
What is control flow?! Mogę Ci podać co chcesz, lecz ty masz dośw. w programowaniu pewnie z 5+ lat a ja? I mi tu z control flowem wyjeżdzasz? :D Podać Ci funkcję main()? czy co i jak?
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: siso w Październik 30, 2010, 22:28:38
Coś mi się widzi, drogi Kolego, że flow masz w całości w kodzie, hmmm, zakodowany :)
W którejś części "Perełek..." jest rozdział "Magia sterowania danymi" czy jakoś tak. Gdybyś odseparował kod od danych, to dane te byłyby właśnie stanem gry. Jeśli masz logikę rozgrywki w kodzie, to zapisz tylko te dane, które na rozgrywkę wpływają, jak radzi Kos, i po bajce.

Jeśli chcesz wiedzieć, gdzie wrócić po wczytaniu, możesz zastosować system checkpoint'ów. Zapis będzie możliwy jedynie w checkpointach, ale wtedy checkpoint jest elementem zapisu. Wczytujesz i jedziesz od tego czheckpointa dalej.

Jakoś tak...

PS.
Flow - to po prostu przepływ, czyli wszystko to, co robi Twój kod, co można by nazwać logiką biznesową, ale z punktu widzenia wykonania, nie definicji. Czyli ciąg wywołań po prostu :)
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Xirdus w Październik 30, 2010, 22:29:31
Jak wybierasz chapter na początku gry? I jak potem wybierasz kolejny?
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 22:32:01
chapter = 1; Po walce z wilkiem :D i zapis odrazu do pliku zmienne i na końcu chapter. I jak LoadGame to jeżeli chapter == 1 przejście do etykietki np. po_walce_wilk; Tylko jak przekazać etykietę z funkcji do main?
EDIT:
Mogę wam wstawić cały kod i program nawet;
http://www.wklej.org/id/409845/
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Xirdus w Październik 30, 2010, 22:44:11
Odrzucając możliwość kompletnego refactoringu, zrób po prostu switcha:
switch (chapter)
{
    case 1: goto adventure;
    case 2: goto przed_wioska;
    case 3: goto wioska;
    // i tak dalej
}
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 22:52:52
Wiem już, dzięki wszyskim za pomoc  8) switch się przyda, ale teraz szukałem na necie i nie znalzazłem nic sensownego. A więc jak zrobić wczytywanie kilku linii lub pojednyczo po kolei, mam to: getline(isave, Hero.name); Ale wiadomo wczytuje tylko jedną pierwszą linijkę, a ja chce wszystkie jak odczytać te linijki??
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Xirdus w Październik 30, 2010, 23:06:38
robisz to kilka razy -.-
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: snajper_44 w Październik 30, 2010, 23:13:32
"no matching function for call to `getline(std::fstream&, int&)'" błąd przy 'kilka razy'. Przecież będzie wczytywał za każdym razem pierwszą linię nie?
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: cybek w Listopad 01, 2010, 18:15:41
do wczytywania zmiennych np. int używa się operatora >>, do wczytania większej ilości tekstu możesz użyć metody fstream'a: read
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Avaj w Listopad 01, 2010, 18:31:07
getline, jak sama nazwa wskazuje, wczytuje linię, nie liczbę.
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Rokuzo w Listopad 01, 2010, 21:14:29
???

U can`t touch this :)


char Bufor[100];
fstream isave;
isave.open("frpg_dbsv");
while(!isave.eof())
{
isave.getline(Bufor, 99, '\n');
sscanf(Bufor, "%s", &Hero.name);

        isave.getline(Bufor, 99, '\n');
sscanf(Bufor, "%o", &Hero.hp);

       //I tak dalej ... poczytaj trochę o tym :)
}
isave.close();

Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Avaj w Listopad 01, 2010, 22:11:38
@up

jeśli linijka będzie miała więcej niż 99 znaków to ci się app wykrzaczy
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Xirdus w Listopad 01, 2010, 22:15:34
jeśli linijka będzie miała więcej niż 99 znaków to ci się app wykrzaczy
Programista musi zadbać o to, by tak nigdy nie było :)
Tytuł: Odp: [C++]Zapis stanu gry
Wiadomość wysłana przez: Rokuzo w Listopad 02, 2010, 16:11:57
1. Może sobie policzyć ile jest znaków w linii i zrobić to na tablicy dynamicznej ew. pobawić się wektorami.
2. 99 znaków raczej starczy do tego co on chciał uzyskać zresztą nie musi to być 99 ... może dać więcej.

Jak on chciał wczytać nick bohatera .... to będzie na pewno mniej niż 20 znaków ;p więc do czegoś takiego to starczy :)