Przepisanie kodu gry na kod obiektowy

0

Witam,

od 3 dni zacząłem swoją przygodę z c++ i postanowiłem napisać swoją 1 grę.

zrzut.png

jeśli zdjęcie doszło to po napisaniu kodu o dziwo wszystko działa ale wygląda on jakby pisany przez małosprynte dziecko.

pozycja: x, y : poruszamy się "w","s","a","d" i zapisane jest to w void input();
a system opiera się o oś kartezjańską więc jest banalny ( "d" x+=1) cała filozofia systemu ruchów.

na początku wybieramy czy chcemy byc "wojownikiem" , "Magiem", "Łowcą".
po wyborze klasy są nadane atrybuty hp, dmg itp.

switch(command)
{  case 1:   {  hp=30; dmg=5;} ..... np. dla wojownika. 

do tego oczywiście void walka, sklep, plecak bo tylko to na razie działa jak wchodzimy do różnych miast;p
z tym, że wszystkie wybory obsługuje 1 switch ;p więc plecak, zaklecia i mikstury to liczby a jak chcesz wejść do sklepu to musisz to wpisać nooo ale ;p

i teraz moje pytanie ...

po zobaczeniu czegoś takiego jak podejście obiektowe ;p próbuję poukładać to jakoś w głowię.
Chciałbym przepisać obecną grę w tym podejściu bo w sumie mam nawet na nią koncepcję itp ale nie wiem jak się zabrać myślowo.

to ja mam wszystko tworzyć jako klasy? gre; system ruchu; walki; czy walkę np umieszczamy w klasie ?

class Wojownik
{
  string: imie;
  int hp;
  .......
void walka(); 

???

a jak zrobię przeciwnika klase i chcę żeby miał losowe parametry to czy mogę w konstruktorach zawierać tego typu polecenia rand? ? lub np. jakieś if'y dodawać??

a jak np. mam wybór klasy i tworzenie nowego gracza.
to stworzę ją za pomocą voida czy konstruktora?
jeśli konstruktora to czy w nim mogę normalnie zawrzeć komendy cout << " podaj imie wojownika"; cin>>imie; dla użytkownika aby to użytkownik nadał wartości?
czy konstruktor sam nadaje a użytkownik wtedy nie może?

2

Konstruktor to nie miejsce na losowanie liczb albo interakcja z interfejsem użytkownika.

0

Dziękuję za radę...teraz nie będę z tym kombinował a już próby były :p
Proceduralnie to wiem jak opisać ale obiektowo nie mam pojęcia bo nie wiem jak sobie to w głowie poukładać:(((

mianowicie stworzyłem klasę wojownika:

screenshot-20180823210127.png

to jeśli np zrobię klasę wroga to jak mam się odnieść do parametrów np hp czy dmg skoro wyskakuje mi że p1 nie istnieje albo brak atrybutów int hp.

switch(commandw)
{
   case 1:
      {   
           wojownik p1;
          p1.stworz_postac();
          
      }break;

a później chce to wyświetlić to wyskakuje brak int hp
jak do innych funkcji zainicjować atrybuty postaci ?
skoro wyskakuje mi, że nie istnieją choć zostaną stworzone w przebiegu gry.
hm...milion myśli i żadnej konkretnej jak to wszystko połączyć ;/

bo np tak wyglądał system walki:
to jeśli stworzę 2 klasy Wojownika i Wroga to jak mogę to połączyć, żeby stworzyć void trap(); ?
w momencie poruszania się jak będziemy poza miastem na pozycjach x=15, y=15 ma wyskakiwać funkcja tworząca losowego wroga z klasy i losować np. 75%, że dojdzie do walki i wtedy void fight(); Ale jak to poskładać obiektowo :/ ?? eh...

void fight()
{
    cout << " " << endl;
    cout << "    Przygotuj sie do walki!" << endl; Sleep(3500);

    while(ehp>=1 && hp>=1)
    {
        system("cls");
        cout << " " << endl;
        cout << " Gracz        hp: " << hp << " dmg: " << dmg << endl;
        cout << " Przeciwnik   hp: " << ehp << " dmg: " << edmg << endl << endl;

        fdmg = rand() % dmg;
        cout << " Gracz zadaje: " << fdmg << endl;
        ehp=ehp-fdmg;
        Sleep(500);

        fedmg = rand() % edmg;
        cout << " Przeciwnik zadaje: " << fedmg << endl << endl;
        hp=hp-fedmg;
        Sleep(500);
    }

    if (ehp<=0)
        {
            system("cls");
            cout << "" << endl;
            cout << " Wygrales!!!" << endl;
            cout << " -----------" << endl << endl;
            cout << " zloto: +7" << endl;
            cout << " exp: +12" << endl;
            Sleep(4000);
            zloto = zloto +7;
            exp = exp +12;
            logic();
        }
        else if (hp<=0)
        {
            system("cls");
            cout << " Zdechles!";
            Sleep(2500);
            menu();
        }

    gra();

}
0

ale nie wiem jak się zabrać myślowo.

będą ci potrzebne kartki A4 i długopis. I rysujesz np. kwadracik = klasa, łączysz strzałkami, myślisz o tym jak te obiekty będą współpracować.

Projektowanie kodu na większą skalę wymaga myślenia przestrzennego, a rysowanie na kartce pozwala rozwinąć tego rodzaju myślenie (potem na jakimś etapie już się kartki nie potrzebuje).

Oczywiście nie uda się często dobrze zaprojektować wszystkiego za pierwszym razem, ale zawsze można napisać jakiś kod, zobaczyć na ile się to sprawdza, a potem go przerobić, jeśli się okaże, że dany podział na klasy jest nie do końca dobrym pomysłem.

int dmg /// obrazenia zadawane przez postac

a nie lepiej po prostu nazwać zmienną normalnie, czyli bez skrótów tylko damage albo nawet characterInflictedDamage a ten komentarz "obrazenia zadawane przez postac" po prostu skasować? W ogóle te komentarze trochę od czapy.

to ja mam wszystko tworzyć jako klasy? gre; system ruchu; walki; czy walkę np umieszczamy w klasie ?

Czemu od razu o klasach myślisz? Programujesz w C++ więc masz to szczęście, że masz coś takiego jak funkcje albo np. struktury. Twój kod nie jest podzielony nawet na funkcje z tego co widzę.

Myślę, że napisanie tego na kodzie proceduralnym, na zwykłych funkcjach i jakichś strukturach danych (choćby strukturach z C++, tablicach itp.) to już byłby pewien krok w przód w stosunku do bezładnego switcha i zmiennych globalnych.

0
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <cstdlib>
#include <time.h>

using namespace std;

bool player_d = false;

int command;

string ruch;

///player
int hp, dmg, fhp, fdmg;
float exp, nexp=100;
int lvl=1;
///wilk
int ehp, edmg, fedmg;

int x = 2, y = 2;
/// mikstury
int xz = 3, xs = 1;

/// zloto

int zloto = 0;

///sklep
int mzs = 5;

void menu();
void gra();
void input();
void map();
void logic();
void stats();
void klasa();
void fight();
void wilk();
void plecak();
void sklep();
void miksturaz();
void mzsk();
void miksturas();

void menu()
{
    system("cls");
    cout << "" << endl;
    cout << " Witaj w grze RPG" << endl;
    cout << " ----------------" << endl <<endl;

    cout << " 1. Start Gry!" << endl;
    cout << " 2. Wyjscie z Gry!" << endl << endl;
    cin >> command;

    switch(command)
    {
    case 1:
        {
            klasa();
        }break;
    case 2:
        {
            cout << "Gra zostanie wylaczona!" ; Sleep(1500);
            exit(0);
        }break;
    default:
        {
            cout << "Nie ma takiej opcji!" << endl; Sleep(1500);
            menu();
        }break;
    }
}

void klasa()
{
    system("cls");
    cout<< " " <<endl;
    cout << " Kim chcesz zostac?" << endl;
    cout << " ------------------" << endl << endl;
    cout << " 1. Wojownik" << endl;
    cout << " 2. Lowca" << endl;
    cout << " 3. Mag" << endl << endl;
    cin >> command;

    switch(command)
    {
    case 1:
        {
            hp = 30;
            dmg = 5;
            gra();
         }break;

    case 2:
        {
            hp = 23;
            dmg = 8;
            gra();
         }break;

    case 3:
        {
            hp = 15;
            dmg = 13;
            gra();
         }break;

    default:
        {
            cout << "Nie ma takiej klasy!" << endl; Sleep(1500);
            klasa();
        }break;
    }
}
void gra()
{
    system("cls");
    stats();
    map();
    input();
    logic();
}
void map()
{
    if(x==2 && y==2)
    {
        cout << "    Gniezno " << endl;
        cout << "    ------- " << endl << endl;
        cout << "    Witaj w naszym miescie..." << endl;
        cout << "    gdzie chcesz sie udac?" << endl << endl;
        cout << "    1. Walka" << endl;
        cout << "    2. Sklep" << endl;
        cout << "    3. Swiatynia" << endl << endl;
    }
    if(x==2 && y==3)
    {
        cout << "Warszawa!" << endl;
    }
    if(x==4 && y==2)
    {
        cout << "    Lublin " << endl;
        cout << "    ------- " << endl << endl;
        cout << "    jestes na zadupiu...tu wrony nawet nie dolatuja." << endl;
    }  
}

void stats()
{
        cout << "" << endl;
       cout << "  **************************" << endl;
     cout << "    pozycja: x:" << x << " y:" << y << endl;
    cout << "    hp: " << hp << endl;
    cout << "    dmg: " << dmg << endl;
    cout << "    lvl: " << lvl << endl;
    cout << "    exp: " << exp << "/" << nexp << "    zloto: " << zloto << endl;
    cout << "  **************************" << endl;
    cout << "    zawartosc plecaka: 1 " << endl;
    cout << "    ksiega zaklec: 2 "<< endl;
    cout << "    tworzenie mikstur: 3" << endl;
    cout << "  **************************" << endl << endl;
}

void plecak()
{
    system("cls");
    cout << " " << endl;
    cout << " Obecny poziom hp : " << hp << endl << " Obecny poziom dmg: " << dmg << endl << endl;
    cout << " Zawartosc Plecaka" << endl;
    cout << " -----------------" << endl << endl;
    cout << " 1. Mikstura zdrowia +10: " << "liczba " << xz << endl;
    cout << " 2. Mikstura sily +2: " << "liczba "<< xs << endl << endl;
    cout << " 3. Wyjscie" << endl << endl;
    cout << " co chcesz uzyc??" << endl;
    cin >> command;

    switch(command)
    {
    case 1:
        {
           miksturaz();
           plecak();
        }break;
    case 2:
        {
            miksturas();
            plecak();
        }break;
    case 3:
        {
            gra();
        }break;
    default:
    {
        cout << "nie ma wybierz to co jest!";
        Sleep(3000);
        plecak();
    }break;
    }
}

void input()
{
    cin >> ruch;

    if(ruch=="w")
    {
        y=y+1;
    }
    else if(ruch=="s")
    {
        y=y-1;
    }
    else if(ruch=="a")
    {
        x=x-1;
    }
    else if(ruch=="d")
    {
        x=x+1;
    }
    else if(ruch=="walka")
    {
        wilk();
        fight();
    }
    else if(ruch=="1")
    {
        plecak();
    }
    else if(ruch=="sklep")
    {
        sklep();
    }
    else
    {
        cout << "Nie ma takiego ruchu" << endl; Sleep(1500);
    }
}

void logic()
{
    if(exp >= nexp)
    {
        exp=0;
        lvl++;
        hp+=3;
        dmg+=2;
        nexp=nexp*1.15;
    }
}

void fight()
{
    cout << " " << endl;
    cout << "    Przygotuj sie do walki!" << endl; Sleep(3500);

    while(ehp>=1 && hp>=1)
    {
        system("cls");
        cout << " " << endl;
        cout << " Gracz        hp: " << hp << " dmg: " << dmg << endl;
        cout << " Przeciwnik   hp: " << ehp << " dmg: " << edmg << endl << endl;

        fdmg = rand() % dmg;
        cout << " Gracz zadaje: " << fdmg << endl;
        ehp=ehp-fdmg;
        Sleep(500);

        fedmg = rand() % edmg;
        cout << " Przeciwnik zadaje: " << fedmg << endl << endl;
        hp=hp-fedmg;
        Sleep(500);
    }

    if (ehp<=0)
        {
            system("cls");
            cout << "" << endl;
            cout << " Wygrales!!!" << endl;
            cout << " -----------" << endl << endl;
            cout << " zloto: +7" << endl;
            cout << " exp: +12" << endl;
            Sleep(4000);
            zloto = zloto +7;
            exp = exp +12;
            logic();
        }
        else if (hp<=0)
        {
            system("cls");
            cout << " Zdechles!";
            Sleep(2500);
            menu();
        }
    gra();
}

void wilk()
{
    ehp = 15;
    edmg = 3;
}

void miksturaz()
{
    if(xz>0)
    {
         xz--;
         hp+=10;
    }
    else if (xz==0)
    {
        cout << "nie masz mikstury!" << endl;
        Sleep(2500);
        plecak();
    }
}

void miksturas()
{
    if(xs>0)
    {
         xs--;
         dmg+=2;
    }
    else if (xs==0)
    {
        cout << "nie masz mikstury!" << endl;
        Sleep(2500);
        plecak();
    }
}

void mzsk()
{
    if(mzs>0)
    {
         if(zloto>0)
         {
             zloto=zloto-10;
             mzs--;
             xz++;
        }
         else
         {
             cout << " nie stac cie" << endl;
             Sleep(1500);
         }
    }
    else if (mzs==0)
    {
        cout << "nie masz mikstury!" << endl;
        Sleep(2500);
        sklep();
    }
}
void sklep()
{
    system("cls");

    cout<<endl;
    cout << " Witaj w SKLEPIE!"<<endl;
    cout << " co chcesz kupic?"<<endl;
    cout << " -----------------"<<endl;
    cout << " masz: " << zloto << " zlota" << endl << endl;
    cout << " 1. mikstura zdrowia +5 sztuk: 0" << endl;
    cout << " 2. mikstura zdrowia +10 sztuk " << mzs <<" 10 zlota"<< endl;
    cout << " 3. wyjscie" << endl << endl;
     cin >> command;

    switch(command)
    {
    case 1:
        {
           sklep();
        }break;
    case 2:
        {
            mzsk();
            sklep();
        }break;
    case 3:
        {
            gra();
        }break;
    default:
    {
        cout << "nie ma wybierz to co jest!";
        Sleep(3000);
        sklep();
    }break;
    }
}

Tak wyglądał kod pisząc proceduralnie.
oczywiście ma sporo braków bo nie ma zabezpieczeń itp.
ale pisałem go, żeby zrozumieć funkcje, pętle itp

teraz nie wiem w którym miejscu utworzyć atrybuty dla danej postaci maga, wojownika i przeciwnika.
bo jak umieszczę w klasach to nie mogę się do nich odnieść w oddzielnych funkcjach choć mają dostęp public:
a skoro atrybuty nadaję w wojownik::stworz_postać to one nie istnieją w chwili odpalenia kodu więc ich nie widać i jest błąd.

więc jak połączyć 2 klasy class wojownik i class przeciwnik w system walki ?
gdzie umieścić atrybuty? konstruktor je nadaje ? jesli tak to ok ... ale jak się później do nich odnieść w innej funkcji ?
bo podczas odpalenia kod nie widzi obiektu z klasy wojownik skoro nie został stworzony :/
jakiś prosty przykład rozjaśnił by mi całkowicie podejście obiektowe :)

0
  1. Ten kod który wkleiłeś nie jest obiektowy, tylko proceduralny.
  2. Zanim zaczniesz pisać kod obiektowy musisz zrozumieć różnicę między interfejsem, a implementacją.
  3. Zanim to zrozumiesz, musisz wiedzieć jak skorzystać z polimorfizmu.
  4. Zanim zaczniesz z polimorfizmem, musisz wiedzieć jak korzystać z klas, interfejsów i struktur.

Więc proponuję żebyś zaczął od punktu 4tego, i zaczął dzielić swój program na struktury. Chodzi o to, żeby dane o wspólnym przeznaczeniu (np statystki bohatera - hp, exp, lvl - trzymać razem, a statystyki jakich przedmiotów - atak, cena - osobno).

struct Postac {
    int hp,damage,  gold, exp, level;
    Postac(int poczatkowyHp, int poczatkowyDamage) {
        this->hp = poczatkowyHp;
        this->damage = poczatkowyDamage;
        this->gold = 0;     // jeśli uznasz że początkowo powinno być jakaś ilośc kasy,
        this->exp = 0;      // to przekaż to przez parametr konstruktora tak jak hp
        this->level = 1;
    }
};

struct Wilk {
    int hp, damage;
    Wilk(int poczatkowyHp) {
        this->hp = paczatkowyHp;
        this->damage = 20;
    }
}

Tips:

  1. Nazywaj zmiennej sensownie: zamiast edmg - enemyDamage, zamiast xy - mixtureHealth czy coś podobnego. Zmienna mzs nie mam pojęcia do czego służy, więc nazwij ją lepiej. Wyjątki jak hp lub lvl są ok.
  2. Staraj się używać pętli, zamiast rekurencji. Np w metodzie klasa() wołasz potem klasa(), to jest troszkę średni design. Pętla lepiej przedstawiałaby intencje
Postac* createPostac() {
  while (true) {
    clearScreen();
    cout << " " << endl;
    cout << " Kim chcesz zostac?" << endl;
    cout << " ------------------" << endl << endl;
    cout << " 1. Wojownik" << endl;
    cout << " 2. Lowca" << endl;
    cout << " 3. Mag" << endl << endl;
    int command;
    cin >> command;

    switch (command) {
    case 1:
      return new Postac(30, 5);
    case 2:
      return new Postac(23, 8);
    case 3:
      return new Postac(15, 13);
    default:
      cout << "Nie ma takiej klasy!" << endl;
      Sleep(1500);
    }
  }
}

void clearScreen() {
  system("cls");
}

int main() {
    Postac* postac = createPostac();
    gra(postac);
    delete postac;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1