DragonSoul
28-06-2008, 18:13
Nemam iskustva u pisanju tutoriala, tako da se nadam da će ovo ispasti dobro. Ali prvo da se zahvalim RayDX-u za source od Path of a Heroa, koji mi je dao ideju da napravim ovo i razjasnio nekoliko stvari u C++u (zbog kojih sam odustao od C++a). Pa ajmo:
Ovaj tutorial će pokazati kako napraviti Inventory system za RPG (http://www.rpg-zone.info)Sigre i jedan mini shop. Ali prije nego počnem išta objašnjavati, evo source:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
class Weapon
{
public:
Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID); //konstruktor
~Weapon(); //destruktor
//nisam pravio private, jer u ovom primjeru mi ne trebaju get metode
string wName; //ime
int minPower; //minimalna snaga, najmanja moguća šteta - neće se koristiti u tutorialu, jer ne napadamo
int maxPower; //maximalna snaga, najveća moguća šteta - neće se koristiti, iz istih razloga
int cijena; //cijena itema, za shop explain
int ID; //služi za indexiranje itema, po njemu ćemo izbacivati iteme iz inventorya
};
Weapon::Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID)
{
wName = setName;
minPower = setMinPower;
maxPower = setMaxPower;
cijena = setCijena;
ID = setID;
//pri konstrukciji objekta se popunjuju parametri
}
Weapon::~Weapon()
{
}
//---- Globalne varijable
int Gold; //za shop explain
int ShopChoice; //izbor što ćemo kupiti
bool done; //bool za glavni loop
Weapon* inventory[10]; //Naš inventory
int BuySell; //služiti će za izbor dali želimo kupovati ili prodavati
bool ToBuy; //služiti će za parametar dali kupujemo ili prodajemo
//---- Prototipovi funkcija
void Shop(); //funkcija našeg shopa
void AddToInventory(Weapon* item); //funkcija koja dodaje item u inventory
void RemoveFromInventory(Weapon* item); //funkcija koja uklanja item iz inventorya
void ShowInventory(); //prikazuje inventory
int main()
{
Gold = 10000; //malkoc sam pretjerao :)
//imamo 10 slotova, no to sam tek
//kasno odlučio tako da je ovo hard coding
//ali bi se ovo 10 moglo zamjeniti s
//varijablom "maxslots" koju nisam napravio
//a lijen sam da ju implementiram
for(int i = 0; i != 10; i++)
{
inventory[i]S= 0;
}
//ovaj tu loop nam "nulira" inventory
//znači, postavljamo sva polja u arrayu na 0
//tako da ćemo kasnije znati koji je slot prazan
done = true; //nisam prije ovo napravio, ali mogao sam
//main loop
while(done)
{
cout << "Inventory and Shop Explain v1.0, DragonSoul (c) 2008\n";
cout << "Gold: " << Gold << endl;
cout << "1. Buy\n";
cout << "2. Sell\n";
cin >> BuySell;
switch(BuySell)
{
case 1:
ToBuy = true;
break;
case 2:
ToBuy = false;
break;
}
//ovaj nam switch uređuje bool ToBuy, koji će
//kasnije odrediti dali na snagu stupa
//AddToInventory(Weapon* item) ili
//RemoveFromInventory(Weapon* item)
Shop(); //pokreće se shop u kojem i kupujemo i prodajemo
}
cin.get();
cin.get();
//čini mi se da je ovo unreachable code
//ali mi se ne da sada pokusirati
}
void Shop()
{
Weapon* item; //stvaramo naš prazni item
//to možemo zamisliti kao zamisao
//"Želim kupiti item"
//ali bez da znamo koji
cout << "1. Sword\n";
cout << "2. Axe\n";
cout << "3. Bow\n";
cout << "4. Room/time eater\n";
cout << "5. Multidimension bomb\n";
cout << "6. Exit\n";
cin >> ShopChoice;
//ovaj switch nam kreira taj item koji mi želimo
switch(ShopChoice)
{
case 1:
item = new Weapon("Sword", 5, 10, 100, 1);
break;
case 2:
item = new Weapon("Axe", 10, 15, 150, 2);
break;
case 3:
item = new Weapon("Bow", 7, 17, 211, 3);
break;
case 4:
item = new Weapon("Room/time eater", 100, 10000, 9058, 4);
break;
case 5:
item = new Weapon("Multidimension bomb", 10000, 50000, 5432, 5);
break;
case 6:
item = new Weapon("Exit", 11, 111, 1111, 6);
break;
default:
cout << "Zeznio si se. Sad fino ugasi app i ponovo.\n";
break;
}
//Ovo nam provjerava dali taj item koji
//želimo kupiti ne košta previše
//u suprotnom bi end-user jednostavno
//mogao kupovati do bola na kredit
//koji nikada nebi vratio
if(item->cijena > Gold)
{
cout << "Nemas dosta novaca.\n";
}
else
{
//e, to je sada onaj ToBuy iz main loopa
//i on nam određuje dali kupujemo ili
//prodajemo item koji smo odabrali
switch(ToBuy)
{
case true:
Gold -= item->cijena;
AddToInventory(item);
break;
case false:
Gold += item->cijena;
RemoveFromInventory(item);
break;
}
}
//prikazuje nam inventory
cout << "Imas sljedece iteme u inventoryu:\n";
ShowInventory(); //ovo zapravo prikazuje, ono gore je samo nešto kao naslov
cin.get();
cin.get();
}
void AddToInventory(Weapon* item)
{
for(int i = 0; i != 10; i++)
{
if(inventory[i]S== 0)
{
inventory[i]S= item;
cout << item->wName << " je dodan u inventory.\n";
break;
}
else
{
}
}
}
void RemoveFromInventory(Weapon* item)
{
int i = 0; //služiti će kao pokazatelj slota u inventoryu
while(i <= 10) //dok je i manji od broja slotova
{
if(inventory[i]S!= 0) //ako inventory slot nije prazan ("nuliran")
{
if(inventory[i]->ID == item->ID)
//ako item u inventory slotu ima isti ID
//kao traženi item
{
inventory[i]S= 0; //nuliraj item
cout << item->wName << " je uklonjen iz inventorya.";
//javi end-useru da je uklonjeno
i = 11; //i = maxslotova+1, tako da se loop više ne loopa
break;
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
}
void ShowInventory()
{
for(int i = 0; i != 10 && i < 10; i++)
//za svaki i koji počinje od 0, dok i nije 10
//i "i" je manji od 10 obavi svoje i povečaj i za jedan
{
if(inventory[i]S!= 0) //ako slot nije prazan
{
cout << inventory[i]->wName << endl; //prikaži ime itema
}
else
{
cout << "<Prazan slot>\n"; //u suprotnom napiši da je slot prazan
}
}
}
Nisam razdvajao definiciju klase, metoda i glavnu igru, jer za ovaj mali primjer nije potrebno komplicirati. Pravio sam globalne varijable jer mi se nisam htio dodatno komplicirati stvar, ovako se sve vidi odmah na početku. Idemo onda redom:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
Ovo je ja mislim svima jasno. Includeamo sve što nam je potrebno i te compileru kažemo da koristi namespace std, tako da ne moram uvijek upisivati std::cout ili std::cin ili std::string.
Sclass Weapon
{
public:
Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID); //konstruktor
~Weapon(); //destruktor
//nisam pravio private, jer u ovom primjeru mi ne trebaju get metode
string wName; //ime
int minPower; //minimalna snaga, najmanja moguća šteta - neće se koristiti u tutorialu, jer ne napadamo
int maxPower; //maximalna snaga, najveća moguća šteta - neće se koristiti, iz istih razloga
int cijena; //cijena itema, za shop explain
int ID; //služi za indexiranje itema, po njemu ćemo izbacivati iteme iz inventorya
};
Trudio sam se sve komentirati, ali opet ću pojasniti. Znači, naše oružje ima konstruktor koji odmah postavlja parametre itema. Ovdje bi jedino mogao biti nejasan ID. On nam služi za identifikaciju itema. Mogli smo mi item tražiti i po imenu, ali što ako želimo 2 itema s istim imenom a različitim efektom/snagom, tada bi imali problem.
SWeapon::Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID)
{
wName = setName;
minPower = setMinPower;
maxPower = setMaxPower;
cijena = setCijena;
ID = setID;
//pri konstrukciji objekta se popunjuju parametri
}
Ovo je definicija konstruktora. Konstruktor se poziva kada se objekt stvara. Znači, mi bi sada stvarali oružja s:
Weapon GigaMegaSword(„Giga Mega Sword“, 10, 1000000, 93895, 312);
Iako ja to u ovom primjeru neću tako raditi, to je način na koji se stvaraju objekti.
S//---- Globalne varijable
int Gold; //za shop explain
int ShopChoice; //izbor što ćemo kupiti
bool done; //bool za glavni loop
Weapon* inventory[10]; //Naš inventory
int BuySell; //služiti će za izbor dali želimo kupovati ili prodavati
bool ToBuy; //služiti će za parametar dali kupujemo ili prodajemo
//---- Prototipovi funkcija
void Shop(); //funkcija našeg shopa
void AddToInventory(Weapon* item); //funkcija koja dodaje item u inventory
void RemoveFromInventory(Weapon* item); //funkcija koja uklanja item iz inventorya
void ShowInventory(); //prikazuje inventory
Definicija varijabli i prototipovi funkcija. Ništa posebno.
for(int i = 0; i != 10; i++)
{
inventory[i]S= 0;
}
E, ovdje već postaje zanimljivo. Kao što sam gore u cijelom sourceu komentirao, ovaj nam loop služi za „nuliranje“ slotova inventorya. To će nam služiti da vidimo dali je slot prazan ili ne. Ovdje smo ispraznili „džepove“, tj. slotove. Ovo je neophodno za pravilni rad ovog inventory systema.
Swhile(done)
{
cout << "Inventory and Shop Explain v1.0, DragonSoul (c) 2008\n";
cout << "Gold: " << Gold << endl;
cout << "1. Buy\n";
cout << "2. Sell\n";
cin >> BuySell;
switch(BuySell)
{
case 1:
ToBuy = true;
break;
case 2:
ToBuy = false;
break;
}
//ovaj nam switch uređuje bool ToBuy, koji će
//kasnije odrediti dali na snagu stupa
//AddToInventory(Weapon* item) ili
//RemoveFromInventory(Weapon* item)
Shop(); //pokreće se shop u kojem i kupujemo i prodajemo
}
Ovo nam je glavni loop. On printa naslov u konzolu (zato što sam htio raditi s system(„cls“), ali na kraju nisam), te nas pita dali kupujemo ili prodajemo. Unos se obradi, manipulira se ToBuy, ovisno dali kupujemo (ToBuy = true, ili prodajemo, ToBuy = false). Tek nakon toga se pokreće Shop(). U biti, naš end-user misli da smo konstanto u shopu, ali shop se tek na kraju loopa pokreće.
SWeapon* item;
Ovo nam stvara prazni item. On nam služi kasnije za dodavanje u inventory. On nam je kao kalup u koji ćemo kasnije staviti item, koji ćemo onda staviti u inventory.
Sswitch(ShopChoice)
{
case 1:
item = new Weapon("Sword", 5, 10, 100, 1);
break;
case 2:
item = new Weapon("Axe", 10, 15, 150, 2);
break;
case 3:
item = new Weapon("Bow", 7, 17, 211, 3);
break;
case 4:
item = new Weapon("Room/time eater", 100, 10000, 9058, 4);
break;
case 5:
item = new Weapon("Multidimension bomb", 10000, 50000, 5432, 5);
break;
case 6:
item = new Weapon("Exit", 11, 111, 1111, 6);
break;
default:
cout << "Zeznio si se. Sad fino ugasi app pa ponovo.\n";
break;
}
Ovo nam sada popunjava taj „kalup“. U biti nam je item pointer, a mi sada na tu adresu spremamo objekt s određenim parametrima.
Sif(item->cijena > Gold)
{
cout << "Nemas dosta novaca.\n";
}
else
{
//e, to je sada onaj ToBuy iz main loopa
//i on nam određuje dali kupujemo ili
//prodajemo item koji smo odabrali
switch(ToBuy)
{
case true:
Gold -= item->cijena;
AddToInventory(item);
break;
case false:
Gold += item->cijena;
RemoveFromInventory(item);
break;
}
}
Ovaj algoritam nam provjerava dali taj item iz tog kalupa nije preskup za nas. Ako je cijena veća nego što mi novaca imamo, ne možemo kupiti (zvuči poznato, ne?). E, sad imamo switch(ToBuy). On naš objekt usmjerava u prodaju ili kupnju. Ukoliko kupujemo, pokreće se case true, i mi gubimo novce ali dobivamo item, tj. kupili smo ga, a ako prodajemo, pokreće se case false, mi dobivamo novce, ali gubimo item. ToBuy se manipulira sasvim na početku, u main loopu.
S//prikazuje nam inventory
cout << "Imas sljedece iteme u inventoryu:\n";
ShowInventory(); //ovo zapravo prikazuje, ono gore je samo nešto kao naslov
cin.get();
Jednostavno nam prikazuje iteme koje imamo u inventoryu. Ništa posebno.
Sad idem dalje detaljno objasniti ostale funkcije.
void AddToInventory(Weapon* item)
{
for(int i = 0; i != 10; i++)
{
if(inventory[i]S== 0)
{
inventory[i]S= item;
cout << item->wName << " je dodan u inventory.\n";
break;
}
else
{
}
}
}
Ova funkcija dodaje određeni item u prvi sljedeći prazni slot u našem inventoryu. Drugim riječima, ako ako smo imali 3 itema, prodali 1. Item, ostalo nam je ovakav inventory:
<prazan slot>
Sword
Bow
<prazan slot>…
E, sada naša funkcija ne dodaje item na zadnje mjesto, nego na prvo prazno mjesto, tako da ćemo dobiti ovo:
Multidimension bomb
Sword
Bow
<prazan slot>…
void RemoveFromInventory(Weapon* item)
{
int i = 0; //služiti će kao pokazatelj slota u inventoryu
while(i <= 10) //dok je i manji od broja slotova
{
if(inventory[i]S!= 0) //ako inventory slot nije prazan ("nuliran")
{
if(inventory[i]->ID == item->ID)
//ako item u inventory slotu ima isti ID
//kao traženi item
{
inventory[i]S= 0; //nuliraj item
cout << item->wName << " je uklonjen iz inventorya.";
//javi end-useru da je uklonjeno
i = 11; //i = maxslotova+1, tako da se loop više ne loopa
break;
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
}
Ova funkcija uklanja item iz inventorya. Ona je najkompleksnija u cijelom inventory systemu (uvijek, ne samo u mom). Onda ide kroz inventory i uspoređuje ID njegovih itema s IDem traženog itema. Kad ga nađe izlazimo van iz loopa, u svakom suprotnom slučaju povečavamo i za jedan tako da idemo na sljedeći item.
void ShowInventory()
{
for(int i = 0; i != 10 && i < 10; i++)
//za svaki i koji počinje od 0, dok i nije 10
//i "i" je manji od 10 obavi svoje i povečaj i za jedan
{
if(inventory[i]S!= 0) //ako slot nije prazan
{
cout << inventory[i]->wName << endl; //prikaži ime itema
}
else
{
cout << "<Prazan slot>\n"; //u suprotnom napiši da je slot prazan
}
}
}
Ovo je najjednostavnija funkcija. Idemo kroz svaki item u inventoryu. Ukoliko item ne postoji, printa se „<prazan slot>“, ako item postoji, printa se njegovo ime. To se može proširiti s opisima, cijenom i sa svim mogućim, samo malo dobre volje.
Evo, smatram da sam obradio kompletni source i da će nekome ovo poslužiti. Uklanjanje itema iz inventorya ima bug, tj. namjerno sam ga ostavio. U biti ako item ne postoji u inventoryu, primjer se sruši. To vam ostavljam kao zadaću da napravite sami :)
Slobodno koristite ovaj source u svom projektu, kopirajte i tutorial, samo stavite mene kao autora (tutoriala, ne projekta) :D
Ovaj tutorial će pokazati kako napraviti Inventory system za RPG (http://www.rpg-zone.info)Sigre i jedan mini shop. Ali prije nego počnem išta objašnjavati, evo source:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
class Weapon
{
public:
Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID); //konstruktor
~Weapon(); //destruktor
//nisam pravio private, jer u ovom primjeru mi ne trebaju get metode
string wName; //ime
int minPower; //minimalna snaga, najmanja moguća šteta - neće se koristiti u tutorialu, jer ne napadamo
int maxPower; //maximalna snaga, najveća moguća šteta - neće se koristiti, iz istih razloga
int cijena; //cijena itema, za shop explain
int ID; //služi za indexiranje itema, po njemu ćemo izbacivati iteme iz inventorya
};
Weapon::Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID)
{
wName = setName;
minPower = setMinPower;
maxPower = setMaxPower;
cijena = setCijena;
ID = setID;
//pri konstrukciji objekta se popunjuju parametri
}
Weapon::~Weapon()
{
}
//---- Globalne varijable
int Gold; //za shop explain
int ShopChoice; //izbor što ćemo kupiti
bool done; //bool za glavni loop
Weapon* inventory[10]; //Naš inventory
int BuySell; //služiti će za izbor dali želimo kupovati ili prodavati
bool ToBuy; //služiti će za parametar dali kupujemo ili prodajemo
//---- Prototipovi funkcija
void Shop(); //funkcija našeg shopa
void AddToInventory(Weapon* item); //funkcija koja dodaje item u inventory
void RemoveFromInventory(Weapon* item); //funkcija koja uklanja item iz inventorya
void ShowInventory(); //prikazuje inventory
int main()
{
Gold = 10000; //malkoc sam pretjerao :)
//imamo 10 slotova, no to sam tek
//kasno odlučio tako da je ovo hard coding
//ali bi se ovo 10 moglo zamjeniti s
//varijablom "maxslots" koju nisam napravio
//a lijen sam da ju implementiram
for(int i = 0; i != 10; i++)
{
inventory[i]S= 0;
}
//ovaj tu loop nam "nulira" inventory
//znači, postavljamo sva polja u arrayu na 0
//tako da ćemo kasnije znati koji je slot prazan
done = true; //nisam prije ovo napravio, ali mogao sam
//main loop
while(done)
{
cout << "Inventory and Shop Explain v1.0, DragonSoul (c) 2008\n";
cout << "Gold: " << Gold << endl;
cout << "1. Buy\n";
cout << "2. Sell\n";
cin >> BuySell;
switch(BuySell)
{
case 1:
ToBuy = true;
break;
case 2:
ToBuy = false;
break;
}
//ovaj nam switch uređuje bool ToBuy, koji će
//kasnije odrediti dali na snagu stupa
//AddToInventory(Weapon* item) ili
//RemoveFromInventory(Weapon* item)
Shop(); //pokreće se shop u kojem i kupujemo i prodajemo
}
cin.get();
cin.get();
//čini mi se da je ovo unreachable code
//ali mi se ne da sada pokusirati
}
void Shop()
{
Weapon* item; //stvaramo naš prazni item
//to možemo zamisliti kao zamisao
//"Želim kupiti item"
//ali bez da znamo koji
cout << "1. Sword\n";
cout << "2. Axe\n";
cout << "3. Bow\n";
cout << "4. Room/time eater\n";
cout << "5. Multidimension bomb\n";
cout << "6. Exit\n";
cin >> ShopChoice;
//ovaj switch nam kreira taj item koji mi želimo
switch(ShopChoice)
{
case 1:
item = new Weapon("Sword", 5, 10, 100, 1);
break;
case 2:
item = new Weapon("Axe", 10, 15, 150, 2);
break;
case 3:
item = new Weapon("Bow", 7, 17, 211, 3);
break;
case 4:
item = new Weapon("Room/time eater", 100, 10000, 9058, 4);
break;
case 5:
item = new Weapon("Multidimension bomb", 10000, 50000, 5432, 5);
break;
case 6:
item = new Weapon("Exit", 11, 111, 1111, 6);
break;
default:
cout << "Zeznio si se. Sad fino ugasi app i ponovo.\n";
break;
}
//Ovo nam provjerava dali taj item koji
//želimo kupiti ne košta previše
//u suprotnom bi end-user jednostavno
//mogao kupovati do bola na kredit
//koji nikada nebi vratio
if(item->cijena > Gold)
{
cout << "Nemas dosta novaca.\n";
}
else
{
//e, to je sada onaj ToBuy iz main loopa
//i on nam određuje dali kupujemo ili
//prodajemo item koji smo odabrali
switch(ToBuy)
{
case true:
Gold -= item->cijena;
AddToInventory(item);
break;
case false:
Gold += item->cijena;
RemoveFromInventory(item);
break;
}
}
//prikazuje nam inventory
cout << "Imas sljedece iteme u inventoryu:\n";
ShowInventory(); //ovo zapravo prikazuje, ono gore je samo nešto kao naslov
cin.get();
cin.get();
}
void AddToInventory(Weapon* item)
{
for(int i = 0; i != 10; i++)
{
if(inventory[i]S== 0)
{
inventory[i]S= item;
cout << item->wName << " je dodan u inventory.\n";
break;
}
else
{
}
}
}
void RemoveFromInventory(Weapon* item)
{
int i = 0; //služiti će kao pokazatelj slota u inventoryu
while(i <= 10) //dok je i manji od broja slotova
{
if(inventory[i]S!= 0) //ako inventory slot nije prazan ("nuliran")
{
if(inventory[i]->ID == item->ID)
//ako item u inventory slotu ima isti ID
//kao traženi item
{
inventory[i]S= 0; //nuliraj item
cout << item->wName << " je uklonjen iz inventorya.";
//javi end-useru da je uklonjeno
i = 11; //i = maxslotova+1, tako da se loop više ne loopa
break;
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
}
void ShowInventory()
{
for(int i = 0; i != 10 && i < 10; i++)
//za svaki i koji počinje od 0, dok i nije 10
//i "i" je manji od 10 obavi svoje i povečaj i za jedan
{
if(inventory[i]S!= 0) //ako slot nije prazan
{
cout << inventory[i]->wName << endl; //prikaži ime itema
}
else
{
cout << "<Prazan slot>\n"; //u suprotnom napiši da je slot prazan
}
}
}
Nisam razdvajao definiciju klase, metoda i glavnu igru, jer za ovaj mali primjer nije potrebno komplicirati. Pravio sam globalne varijable jer mi se nisam htio dodatno komplicirati stvar, ovako se sve vidi odmah na početku. Idemo onda redom:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
Ovo je ja mislim svima jasno. Includeamo sve što nam je potrebno i te compileru kažemo da koristi namespace std, tako da ne moram uvijek upisivati std::cout ili std::cin ili std::string.
Sclass Weapon
{
public:
Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID); //konstruktor
~Weapon(); //destruktor
//nisam pravio private, jer u ovom primjeru mi ne trebaju get metode
string wName; //ime
int minPower; //minimalna snaga, najmanja moguća šteta - neće se koristiti u tutorialu, jer ne napadamo
int maxPower; //maximalna snaga, najveća moguća šteta - neće se koristiti, iz istih razloga
int cijena; //cijena itema, za shop explain
int ID; //služi za indexiranje itema, po njemu ćemo izbacivati iteme iz inventorya
};
Trudio sam se sve komentirati, ali opet ću pojasniti. Znači, naše oružje ima konstruktor koji odmah postavlja parametre itema. Ovdje bi jedino mogao biti nejasan ID. On nam služi za identifikaciju itema. Mogli smo mi item tražiti i po imenu, ali što ako želimo 2 itema s istim imenom a različitim efektom/snagom, tada bi imali problem.
SWeapon::Weapon(string setName, int setMinPower, int setMaxPower, int setCijena, int setID)
{
wName = setName;
minPower = setMinPower;
maxPower = setMaxPower;
cijena = setCijena;
ID = setID;
//pri konstrukciji objekta se popunjuju parametri
}
Ovo je definicija konstruktora. Konstruktor se poziva kada se objekt stvara. Znači, mi bi sada stvarali oružja s:
Weapon GigaMegaSword(„Giga Mega Sword“, 10, 1000000, 93895, 312);
Iako ja to u ovom primjeru neću tako raditi, to je način na koji se stvaraju objekti.
S//---- Globalne varijable
int Gold; //za shop explain
int ShopChoice; //izbor što ćemo kupiti
bool done; //bool za glavni loop
Weapon* inventory[10]; //Naš inventory
int BuySell; //služiti će za izbor dali želimo kupovati ili prodavati
bool ToBuy; //služiti će za parametar dali kupujemo ili prodajemo
//---- Prototipovi funkcija
void Shop(); //funkcija našeg shopa
void AddToInventory(Weapon* item); //funkcija koja dodaje item u inventory
void RemoveFromInventory(Weapon* item); //funkcija koja uklanja item iz inventorya
void ShowInventory(); //prikazuje inventory
Definicija varijabli i prototipovi funkcija. Ništa posebno.
for(int i = 0; i != 10; i++)
{
inventory[i]S= 0;
}
E, ovdje već postaje zanimljivo. Kao što sam gore u cijelom sourceu komentirao, ovaj nam loop služi za „nuliranje“ slotova inventorya. To će nam služiti da vidimo dali je slot prazan ili ne. Ovdje smo ispraznili „džepove“, tj. slotove. Ovo je neophodno za pravilni rad ovog inventory systema.
Swhile(done)
{
cout << "Inventory and Shop Explain v1.0, DragonSoul (c) 2008\n";
cout << "Gold: " << Gold << endl;
cout << "1. Buy\n";
cout << "2. Sell\n";
cin >> BuySell;
switch(BuySell)
{
case 1:
ToBuy = true;
break;
case 2:
ToBuy = false;
break;
}
//ovaj nam switch uređuje bool ToBuy, koji će
//kasnije odrediti dali na snagu stupa
//AddToInventory(Weapon* item) ili
//RemoveFromInventory(Weapon* item)
Shop(); //pokreće se shop u kojem i kupujemo i prodajemo
}
Ovo nam je glavni loop. On printa naslov u konzolu (zato što sam htio raditi s system(„cls“), ali na kraju nisam), te nas pita dali kupujemo ili prodajemo. Unos se obradi, manipulira se ToBuy, ovisno dali kupujemo (ToBuy = true, ili prodajemo, ToBuy = false). Tek nakon toga se pokreće Shop(). U biti, naš end-user misli da smo konstanto u shopu, ali shop se tek na kraju loopa pokreće.
SWeapon* item;
Ovo nam stvara prazni item. On nam služi kasnije za dodavanje u inventory. On nam je kao kalup u koji ćemo kasnije staviti item, koji ćemo onda staviti u inventory.
Sswitch(ShopChoice)
{
case 1:
item = new Weapon("Sword", 5, 10, 100, 1);
break;
case 2:
item = new Weapon("Axe", 10, 15, 150, 2);
break;
case 3:
item = new Weapon("Bow", 7, 17, 211, 3);
break;
case 4:
item = new Weapon("Room/time eater", 100, 10000, 9058, 4);
break;
case 5:
item = new Weapon("Multidimension bomb", 10000, 50000, 5432, 5);
break;
case 6:
item = new Weapon("Exit", 11, 111, 1111, 6);
break;
default:
cout << "Zeznio si se. Sad fino ugasi app pa ponovo.\n";
break;
}
Ovo nam sada popunjava taj „kalup“. U biti nam je item pointer, a mi sada na tu adresu spremamo objekt s određenim parametrima.
Sif(item->cijena > Gold)
{
cout << "Nemas dosta novaca.\n";
}
else
{
//e, to je sada onaj ToBuy iz main loopa
//i on nam određuje dali kupujemo ili
//prodajemo item koji smo odabrali
switch(ToBuy)
{
case true:
Gold -= item->cijena;
AddToInventory(item);
break;
case false:
Gold += item->cijena;
RemoveFromInventory(item);
break;
}
}
Ovaj algoritam nam provjerava dali taj item iz tog kalupa nije preskup za nas. Ako je cijena veća nego što mi novaca imamo, ne možemo kupiti (zvuči poznato, ne?). E, sad imamo switch(ToBuy). On naš objekt usmjerava u prodaju ili kupnju. Ukoliko kupujemo, pokreće se case true, i mi gubimo novce ali dobivamo item, tj. kupili smo ga, a ako prodajemo, pokreće se case false, mi dobivamo novce, ali gubimo item. ToBuy se manipulira sasvim na početku, u main loopu.
S//prikazuje nam inventory
cout << "Imas sljedece iteme u inventoryu:\n";
ShowInventory(); //ovo zapravo prikazuje, ono gore je samo nešto kao naslov
cin.get();
Jednostavno nam prikazuje iteme koje imamo u inventoryu. Ništa posebno.
Sad idem dalje detaljno objasniti ostale funkcije.
void AddToInventory(Weapon* item)
{
for(int i = 0; i != 10; i++)
{
if(inventory[i]S== 0)
{
inventory[i]S= item;
cout << item->wName << " je dodan u inventory.\n";
break;
}
else
{
}
}
}
Ova funkcija dodaje određeni item u prvi sljedeći prazni slot u našem inventoryu. Drugim riječima, ako ako smo imali 3 itema, prodali 1. Item, ostalo nam je ovakav inventory:
<prazan slot>
Sword
Bow
<prazan slot>…
E, sada naša funkcija ne dodaje item na zadnje mjesto, nego na prvo prazno mjesto, tako da ćemo dobiti ovo:
Multidimension bomb
Sword
Bow
<prazan slot>…
void RemoveFromInventory(Weapon* item)
{
int i = 0; //služiti će kao pokazatelj slota u inventoryu
while(i <= 10) //dok je i manji od broja slotova
{
if(inventory[i]S!= 0) //ako inventory slot nije prazan ("nuliran")
{
if(inventory[i]->ID == item->ID)
//ako item u inventory slotu ima isti ID
//kao traženi item
{
inventory[i]S= 0; //nuliraj item
cout << item->wName << " je uklonjen iz inventorya.";
//javi end-useru da je uklonjeno
i = 11; //i = maxslotova+1, tako da se loop više ne loopa
break;
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
else
{
i++; //u suprotnom idi jedan slot dalje
}
}
}
Ova funkcija uklanja item iz inventorya. Ona je najkompleksnija u cijelom inventory systemu (uvijek, ne samo u mom). Onda ide kroz inventory i uspoređuje ID njegovih itema s IDem traženog itema. Kad ga nađe izlazimo van iz loopa, u svakom suprotnom slučaju povečavamo i za jedan tako da idemo na sljedeći item.
void ShowInventory()
{
for(int i = 0; i != 10 && i < 10; i++)
//za svaki i koji počinje od 0, dok i nije 10
//i "i" je manji od 10 obavi svoje i povečaj i za jedan
{
if(inventory[i]S!= 0) //ako slot nije prazan
{
cout << inventory[i]->wName << endl; //prikaži ime itema
}
else
{
cout << "<Prazan slot>\n"; //u suprotnom napiši da je slot prazan
}
}
}
Ovo je najjednostavnija funkcija. Idemo kroz svaki item u inventoryu. Ukoliko item ne postoji, printa se „<prazan slot>“, ako item postoji, printa se njegovo ime. To se može proširiti s opisima, cijenom i sa svim mogućim, samo malo dobre volje.
Evo, smatram da sam obradio kompletni source i da će nekome ovo poslužiti. Uklanjanje itema iz inventorya ima bug, tj. namjerno sam ga ostavio. U biti ako item ne postoji u inventoryu, primjer se sruši. To vam ostavljam kao zadaću da napravite sami :)
Slobodno koristite ovaj source u svom projektu, kopirajte i tutorial, samo stavite mene kao autora (tutoriala, ne projekta) :D