18:00 | | Temat wykladu: |
| | GameDev: Poziomy trudności w grach (by Minias, 30.08.06) @ wyklady.net |
| | Komentarze: http://forum.wyklady.net/index.php?topic=82.0 |
18:02 | Minias | no dobra moze zaczniemy |
| Minias | zanim zaczne chce Wam przypomniec ze wyklad bedziecie mogli ocenic po jego zakonczeniu |
| Minias | http://forum.wyklady.net/index.php?topic=82.0 |
| Minias | o tutaj |
18:03 | Minias | no dobra jestem Minias, mam 15 lat interesuje sie ogolnie programowaniem, takze gier :) |
| Minias | dzisiaj poprowadze wyklad o tym, jak od strony programisty wyglada tworzenie poziomow trudnosci w grach |
18:04 | Minias | po kazdym 'fragmencie' bedzie czas na pytania |
| Minias | a te najpilniejsze mozecie zadawac na priv ;) |
| Minias | wyklad dotyczy jezyka C++ |
| Minias | chce jednak przypomniec ze nie sa to ani typowe podstawy, ani kurs jezyka |
18:05 | Minias | zakladam ze czytajacy posiada pewna wiedze z zakresu programowania w C++ |
| Minias | nie znam sie takze na Linuksie, wiec moga byc drobne bledy spowodowane roznicami w sciezkach do bibliotek |
| Minias | itd |
18:06 | Minias | no coz, mam nadzieje ze bede w stanie odpowiedziec na wszystkie wasze pytania :) |
| Minias | wyklad jest wlasciwie podzielony na dwie czesci |
| Minias | tej dotyczacej gier RPG |
| Minias | i tej dotyczacej tradycyjnych shooterow |
| Minias | no i moze cos jeszcze jak mi cos wpadnie do lba w czasie wykladu |
| Minias | :P |
| Minias | no dobra, let's do that :) |
| Minias | (najpierw teoria) |
18:07 | Minias | wiadomo nie od dzis, ze przemierzajac swiat gier RPG natkniemy sie w koncu na potworki |
| Minias | i nic w tym dziwnego bo w koncu cos w tej grze robic trzeba :> |
| Minias | potworki oczywiscie nie daja sobie w kasze dmuchac |
| Minias | i najczesciej stawiaja opor |
| Minias | pierwszy z naszych przykladow dotyczyc bedzie tego |
| Minias | jak wysoki jest to opor tzn |
18:08 | Minias | chcemy zrobic tak, by na odpowiednim poziomie trudnosci zadawaly one mnie lub wiecej obrazen |
| Minias | mniej* |
| Minias | ilustruje to obrazek nr1 |
| Minias | |
18:09 | Minias | nasz cel mozemy zrealizowac za pomoca zmiennej statycznej w klasie |
| Minias | (tu male wyjasnienie bo zmienna statyczna w klasie, a zmienna statyczna w funkcji to zupelnie co innego ;>) |
| Minias | wiec zmienna statyczna w FUNKCJI to taka, ktora zostaje w pamieci nawet po jej wykonaniu |
| Minias | i w kolejnym jej wykonaniu ma ona wartosc, jaka miala ostatnio |
18:10 | Minias | (zwykle zmienne w funkcji sa usuwane z pamieci po jej wykonaniu i pozostaja po nich jedynie smieci) |
| Minias | co do zmiennej statycznej w klasie: zmienna ta jest taka sama w kazdym obiekcie danej klasy |
| Minias | oto przyklad: |
| Minias | #include <iostream> |
| Minias | #include <string> |
| Minias | |
| Minias | using namespace std; |
| Minias | |
18:11 | Minias | class Wyklad |
| Minias | { |
| Minias | public: |
| Minias | static bool moderate; |
| Minias | char autor[80], |
| Minias | temat[80]; |
| Minias | void wyk(); |
| Minias | Wyklad(char *aut, char *tem) |
| Minias | { |
| Minias | strcpy(autor,aut); |
| Minias | strcpy(temat,tem); |
| Minias | { |
| Minias | strcpy(autor,aut); |
| Minias | strcpy(temat,tem); |
| Minias | } |
| Minias | }; |
| Minias | |
| Minias | bool Wyklad::moderate = true; |
| Minias | |
| Minias | void main() |
| Minias | { |
| Minias | Wyklad Pierwszy("Minias", "blabla"); |
| Minias | Wyklad Drugi("sainiM", "bleble"); |
| Minias | cout << Pierwszy.moderate |
| Minias | << endl |
18:12 | Minias | << Drugi.moderate; |
| Minias | system("pause"); |
| Minias | } |
| Minias | widzimy tu zmienna statyczna "klasowa" moderate typu bool (zwraca true lub false [prawda lub falsz]) |
| Minias | definiujemy dwa obiekty typu Wyklad a nastepnie funkcja cout wypisujemy na ekran zawartosc zmiennej moderate |
| Minias | kazdego obiektu z osobna |
| Minias | jak widac w obydwu obiektach zmienna ma ta sama wartosc = 1 (czyli true) co potwierdza "moja" teorie |
| Minias | ze zmienna statyczna w klasie jest zawsze taka sama |
18:13 | Minias | przy okazji chcialbym podkreslic, ze po zakonczeinu modulu klasy stawiamy srednik |
| Minias | no to teraz z tej klasy sprobujmy zbudowac klase potworkow |
| Minias | a wlasciwie klase zmienimy na strukture (wywolujemy slowem 'struct') |
18:14 | Minias | rozni sie od klasy tym ze poprzez domniemanie kazdy jej skladnik jest publiczny (w klasie jest odwrotnie) |
| Minias | podczas wykladu nie bede oddzielal danych prywatnych i publicznych |
| Minias | wiec w gruncie rzeczy struktura jest dla nas korzystniejsza |
| Minias | przerobmy wiec klase na korzystna dla nas strukture: |
18:15 | Minias | struct Monster |
| Minias | { static int trudnosc; |
| Minias | int tMin, tMax; |
| Minias | char tName[20]; |
| Minias | void atak(int tObr); |
| Minias | Monster(char *name, int min, int max) |
| Minias | { |
| Minias | strcpy(tName, name); |
| Minias | tMin = min; |
| Minias | tMax = max; |
| Minias | } |
| Minias | }; |
18:16 | Minias | w taki sposob mamy gotowa strukturke potworkow (ktora w gruncie rzeczy przyda nam sie w duzej czesci wykladu) |
| Minias | mamy tu takze zdefiniowany konstruktor (typu inline) |
| Minias | dopasowuje on gorny i dolny zakres obrazen a takze nazwe potwora |
| Minias | nalezy jednak pamietac by nie przesadzac z konstruktorami / funkcjami typu inline |
18:17 | Minias | sa one szybsze w wykonaniu tylko w przypadku malych funkcji (1, 2 w ostatecznosci 3 linijkowych) |
| Minias | Oczywiscie, zamiast zmiennej statycznej moglibysmy uzyc zmiennej globalnej |
| Minias | ja uzylem zmiennej statycznej poniewaz byl to pierwszy pomysl na jaki wpadlem :) |
| Minias | po prostu tak obmyslilem i tak ma byc ;> |
18:18 | Minias | jak ktos chce moze uzywac zmiennej globalnej (w dalszej czesci wykladu w jednym przypadku i tak jej uzyjemy) |
| Minias | zalozmy ze mamy narazie taki fragment kodu: |
| Minias | #include <iostream> |
| Minias | #include <string> |
| Minias | using namespace std; |
| Minias | inline int random(int nMin, int nMax) |
| Minias | { return rand() % (nMax - nMin + 1) + nMin; |
| Minias | } |
| Minias | |
18:19 | Minias | struct Monster |
| Minias | { |
| Minias | static int trudnosc; |
| Minias | int tMin, tMax; |
| Minias | char tName[20]; |
| Minias | void atak(int tObr); |
| Minias | Monster(char *name, int min, int max) |
| Minias | { |
| Minias | strcpy(tName, name); |
| Minias | tMin = min; |
| Minias | tMax = max; |
| Minias | } |
| Minias | }; |
| Minias | chcemy zrobic tak, by potwor zadawal nam losowe obrazenia |
| Minias | dlatego potrzebna jest nam funkcja "random" |
| Minias | funkcja ta losuje liczbe z przedzialu nMin i nMax |
18:20 | Minias | teraz dobudujmy funkcje 'atak' ze struktury Monster |
| Minias | void Monster::atak(int tObr); |
| Minias | { cout << tName << " zadal Ci " << tObr << " obrazen\n"; |
| Minias | } |
| Minias | na dobra sprawe takze moglaby byc to funkcja inline |
| Minias | przestrzegam jednak, ze funkcje skladniowe danej klasy / struktury sa inline wtedy |
18:21 | Minias | gdy ich definicja znajduje sie wewnatrz modulu klasy / struktury |
| Minias | nie nalezy dodawac 'inline' tak jak w przypadku funkcji random:) |
| Minias | wrocmy do naszego kodu |
| Minias | tu pewne wyjasnienie co do funkcji Monster::atak i tName, ktore sie tam znalazlo |
18:22 | Minias | no bo niby skad ono tam jest? |
| Minias | a wiec jest to zmienna aktualnego obiektu danej klasy / struktury |
| Minias | moglibysmy ja takze oznaczyc wskaznikiem this, tzn |
| Minias | cout << this->tName; |
| Minias | nie jest to jednak wymagane |
| Minias | kompilator sam sobie wstawi ten wskaznik |
| Minias | jak to mozliwe ze sie nie myli? |
18:23 | Minias | otoz, wywolywanie funkcji skladniowej danej klasy jest mozliwe tylko przez obiekt |
| Minias | nie mozemy jej wywolac np. Monster::atak(100); |
| Minias | tylko najpierw musimy zdefiniowac obiekt tej klasy, a dopiero poznije (z tego obiektu!) wywolac funkcje |
| Minias | np. tak: |
| Minias | Monster Ork("Ork", 50, 100); |
18:24 | Minias | Ork.atak(100); |
| Minias | no dobrze |
| Minias | skonczylismy na zbudowaniu funkcji Monster::atak |
| Minias | mamy tam tylko informacje o tym ze potwor zadal nam x obrazen |
| Minias | ale czy napewno? |
| Minias | tak na prawde wcale tego nie zrobil |
| Minias | jak zrobic, aby potwor zadawal REALNE obrazenia, dowiecie sie pozniej :> |
| Minias | w dalszej czesci wykladu |
18:25 | Minias | no dobrze, do naszego kodu wystarczy dobudowac teraz procedure 'main' |
| Minias | int main() |
| Minias | { srand((unsigned int)time((time_t*)NULL)); bool dalej = false; while(!(dalej)) { |
18:26 | Minias | cout << "Podaj poziom trudnosci (1 lub 2 lub 3): "; |
| Minias | cin >> Monster::trudnosc; |
| Minias | if((Monster::trudnosc == 1) || (Monster::trudnosc == 2) || (Monster::trudnosc == 3)) |
| Minias | { |
| Minias | dalej = true; |
| Minias | } |
| Minias | } |
| Minias | int a, b; |
| Minias | a = 5 * Monster::trudnosc; |
| Minias | b = 10 * Monster::trudnosc; |
| Minias | Monster Ork("Ork", a, b); |
| Minias | int obr; |
| Minias | obr = random(Ork.tMin, Ork.tMax); |
| Minias | Ork.atak(obr); |
| Minias | system("pause"); |
| Minias | return 0; |
| Minias | |
| Minias | } |
| Minias | teraz tak: |
| Minias | funkcja srand to generator liczb pseudolosowych |
18:27 | Minias | poslugujemy sie tutaj parametrem 'time', gdyz czas ciagle sie zmienia wiec liczby beda zawsze inaczej przelosowane |
| Minias | jej opis znajdziecie tutaj: |
| Minias | http://www.linuxmanpages.com/man3/srand.3.php |
| Minias | w dalszej czesci kodu (w petli while [wiem ze powyzej nieladnie sie wkleilo, beda pozniej dostepne czytelne kody zrodlowe]) |
18:28 | Minias | wiec w petli while ustalamy poziom trudnosci (a dokladniej okreslamy wartosc zmiennej statycznej trudnosc klasy Monster) |
| Minias | zanim definiujemy obiekt typu Monster, okreslamy dolna i gorna granice obrazen |
| Minias | liczby 5 i 10, to pozycje wyjsciowe, ale ich wlasciwa wartosc obrazen zalezy od wyznaczonego poziomu trudnosci |
18:29 | Minias | dalej znajduje sie definicja obiektu Ork za pomoca naszego konstruktora |
| Minias | nastepnie losujemy liczbe z przedzialu Ork.tMin (minimalne obrazenia) i Ork.tMax (maksymalne obrazenia) |
| Minias | wylosowana liczba to obrazenia, jakie nam w danej chwili zadal ork |
| Minias | ta liczba jest parametrem funkcji Ork.atak |
| Minias | kod, ktory skonstruowalismy znajduje sie tutaj: |
18:30 | Minias | http://wyklady.net/minias/dev01.cpp |
| Minias | sa pytania? |
| Minias | no to lecimy dalej |
18:31 | Minias | powyzej udalo nam sie zrobic tak, by potwor zadawal - zaleznie od poziomu trudnosci - mniej lub wiecej obrazen |
| Minias | teraz zrobimy rzecz odwrotna - czyli jak zrobic, ze to GRACZ zadaje wieksze / mniejsze obrazenai |
| Minias | ilustruje to obrazek nr 2: |
| Minias | |
18:32 | Minias | czesc kodu jest taka sama, takze pozwole sobie ja skopiowac i uzupelnic o braki |
| Minias | #include <iostream> |
| Minias | #include <string> |
| Minias | #include <ctime> |
| Minias | using namespace std; |
| Minias | struct Monster; |
| Minias | Monster *potwor; |
| Minias | int random(int nMin, int nMax) |
| Minias | { return rand() % (nMax - nMin + 1) + nMin; |
| Minias | } |
| Minias | |
| Minias | struct Monster |
| Minias | { |
| Minias | static int trudnosc; |
| Minias | char tName[20]; |
18:33 | Minias | int nowHP, |
| Minias | maxHP; |
| Minias | Monster(char *name, int max) |
| Minias | { |
| Minias | strcpy(tName, name); |
| Minias | maxHP = max; |
| Minias | nowHP = maxHP; |
| Minias | } |
| Minias | }; |
| Minias | |
| Minias | int Monster::trudnosc = 0; |
| Minias | |
| Minias | struct Gracz |
| Minias | { |
| Minias | int minObr, |
| Minias | maxObr; |
| Minias | void atak(int tObr); |
| Minias | Gracz(int minO, int maxO) |
| Minias | { |
| Minias | minObr = minO; |
| Minias | maxObr = maxO; |
| Minias | } |
| Minias | }; |
18:34 | Minias | zanim przejdziemy do omowienia struktury gracza chce zwrocic Wasza uwage na jedna wazna rzecz |
| Minias | mianowicie, na deklaracje (nie mylic z definicja!) struktury ("struct Monster;") oraz jej wskaznik |
| Minias | wskaznik ten przyda sie nam za chwile - a zanim moglismy go utworzyc, musimy znac typ na jaki ma wskazywac |
| Minias | i stad ta deklaracja struktury. Jest to tzw deklaracja zwiastujaca |
| Minias | w powyzszym przykladzie mamy juz dwie struktury: Gracza i potworka |
| Minias | w drugim przypadku mamy takze zmienne okreslajace stan jego zdrowia, ktory po naszych atakach bedzie malal |
18:35 | Minias | zanim opracujemy zawartosc funkcji Gracz::atak() chcialbym najpierw okreslic zawartosc main() |
| Minias | wydaje mi sie, ze w ten sposob latwiej bedzie zrozumiec, co i jak dzieje sie w naszym przykladzie :) |
| Minias | wiec oto zawartosc naszej glownej procedury: |
| Minias | int main() |
| Minias | { srand((unsigned int)time((time_t*)NULL)); bool dalej = false; while(!(dalej)) { |
| Minias | cout << "Podaj poziom trudnosci (1 lub 2 lub 3): "; |
| Minias | cin >> Monster::trudnosc; |
| Minias | if((Monster::trudnosc == 1) || (Monster::trudnosc == 2) || (Monster::trudnosc == 3)) |
| Minias | { |
| Minias | dalej = true; |
18:36 | Minias | } |
| Minias | } |
| Minias | |
| Minias | Monster Ork("Ork", 200); |
| Minias | potwor = &Ork; |
| Minias | int a, b; |
| Minias | cout << "Podaj gorna granice obrazen gracza: "; |
| Minias | cin >> a; |
| Minias | cout << endl; |
| Minias | b = a / Monster::trudnosc; |
| Minias | Gracz Ja(0, b); |
| Minias | while(!(potwor -> nowHP <= 0)) |
| Minias | { |
| Minias | int obr; |
| Minias | obr = random(Ja.minObr,Ja.maxObr); |
| Minias | Ja.atak(obr); |
| Minias | } |
| Minias | system("pause"); |
| Minias | return 0; |
| Minias | |
| Minias | } |
| Minias | pierwsza czesc (do zakonczenia petli while) jest taka sama jak uprzednio |
18:37 | Minias | tworzymy obiekt typu Monster posiadajacy 200 pkt zdrowia (ang heal points - hp) |
| Minias | a nastepnie nakierowujemy na niego wskaznik *potwor |
| Minias | pozniej podajemy wzgledna gorna granice obrazen gracza |
| Minias | wzgledna poniewaz gorna granica to wynik dzielenia naszej liczby przez poziom trudnosci |
18:38 | Minias | nastepnie, dopoki HP Orka nie zejda do 0, wywolywana jest funkcja Gracz::atak |
| Minias | ktora wlasnie zbudujemy: |
| Minias | void Gracz::atak(int tObr) |
| Minias | { |
| Minias | potwor -> nowHP -= tObr; |
| Minias | cout << "Zadales " << tObr << " obrazen\n" |
| Minias | << potwor -> tName << " ma jeszcze " << potwor -> nowHP << " pkt zycia\n"; |
| Minias | } |
| Minias | o to jest juz REALNE zadawanie obrazen o ktorych wspominalem wczesniej :) |
| Minias | dopiero tu widzimy takze role wskaznika *potwor |
18:39 | Minias | otoz okresla on przeciwnika, ktorego aktualnie atakujemy |
| Minias | nie bede sie tu na ten temat za duzo rozpisywal bo nie do konca tego dotyczy wyklad |
| Minias | aczkolwiek troszke nadmienie [teoria] jak zrobic wybieranie "aktualnego" potworka, kiedy jest ich wiecej w grze |
| Minias | no wiec pierwszy ze sposobow to taki ze okreslamy w klasie potworkow ich polozenie (wspolrzedne) |
18:40 | Minias | i jesli gracz bedzie na tych samych wspolrzednych to potwor staje sie aktualnie atakowanym monsterkiem |
| Minias | to taki przyklad dla gier "pikselowych" takich jak przyklady w tym wykladzie ;> |
| Minias | inny sposob to taki, ze jesli w naszym otoczeniu znajduje sie kilka potworow |
18:41 | Minias | to my (jako gracz) wybieramy tego, ktory ma atakowac (np. gra sie zatrzymuje i nas o to pyta) |
| Minias | no ale to tylko teoria, moze kiedys wiecej o tym sie powie ;) |
| Minias | wrocmy do nasszego wykladu |
| Minias | opisalismy juz praktycznie wszystko co potrzebne jest nam do powyzszego przykladu |
| Minias | wiec polaczmy nasze zrodelka w jednosc: |
| Minias | http://wyklady.net/minias/dev02.cpp |
| Minias | pytania? |
18:42 | Minias | no ok, zrobilismy juz zroznicowanie zadawanych obrazen |
| Minias | zarowno gracza jak i potwora |
| Minias | jednak obrazenia to nie wszystko: nawet zadajac duzy bol przeciwnikowi moze on ginac bardzo dlugo (chodzi oczywiscie o gre :P) |
| Minias | zaleznie od stanu jego punktow zdrowia |
18:43 | Minias | tego tez dotyczy nasz kolejny przyklad. Mianowicie napiszemy kod gdzie zaleznie od wyboru trudnosci |
| Minias | potwor bedzie mial wiecej / mniej punktow zdrowia |
| Minias | przedstawia to rys 3 |
| Minias | |
18:44 | Minias | jest to wlasciwie analogia poprzednich dzialan, wiec moze tylko udostepnie caly kod zrodlowy i go pokrotce skomentuje |
| Minias | http://wyklady.net/minias/dev03.cpp |
| Minias | struct Monster |
| Minias | { |
| Minias | static int trudnosc; |
| Minias | char tName[20]; |
| Minias | int nowHP, |
| Minias | maxHP; |
| Minias | Monster(char *name, int max) |
| Minias | { |
| Minias | strcpy(tName, name); |
| Minias | maxHP = max; |
| Minias | nowHP = maxHP; |
| Minias | } |
18:45 | Minias | }; |
| Minias | w strukturze potworkow nie ma nic zaskakujacego, mamy tu tylko pkt zycia i nazwe :) |
| Minias | (pomijam poziom trudnosci i konstruktor) |
| Minias | cout << "Podaj ilosc punktow zycia Orka:>>? "; |
| Minias | cin >> a; |
| Minias | Monster Ork("Ork", (a * Monster::trudnosc)); |
| Minias | cout << "\nOrk na tym poziomie trudnosci posiada " << Ork.maxHP << " punktow zycia" << endl; |
| Minias | a tutaj odbywa sie czynnosc, ktora chcielismy osiagnac |
| Minias | najpierw podajemy wzgledna, maksymalna ilosc pkt zycia Orka |
| Minias | nastepnie za pomoca konstruktora tworzymy obiekt z tym ze nalezy pamietac ze ilosc pkt zdrowia |
| Minias | to nie ta liczba ktora podalismy |
18:46 | Minias | tylko ta liczba PRZEMNOZONA przez nasz poziom trudnosci |
| Minias | nastepnie wyswietlamy, ile wynosi HP Orka na wybranym przez nas poziomie trudnosci ;) |
| Minias | i to tyle jesli chodzi o ten przyklad |
| Minias | pytania? |
18:47 | Minias | no dobra, przerobilismy juz obrazenia i pkt zdrowia oparte o nasz system poziomow trudnosci |
| Minias | teraz zabawimy sie z doswiadczeniem, ktore otrzymujemy od potworkow, ale najpierw troche teorii |
| Minias | zazwyczaj w kazdej grze role-playing system jest oparty na schemacie |
| Minias | gdzie za zabitego potworka zyskujemy doswiadczenie (ang. experience - exp) |
18:48 | Minias | a kiedy otrzymamy jego dostateczna ilosc, przechodzimy na nastepny poziom (ang level - lvl) |
| Minias | wtedy najczesciej zyskujemy kilka punktow doswiadczenia |
| Minias | do rozdzielenia na wybrane statystyki |
| Minias | ilustruje to rys 4 |
18:49 | Minias | |
| Minias | widzimy ze praktycznie wszystko kreci sie wokol zabijania potworkow |
| Minias | mozna powiedziec, ze musimy sie zapetlic, aby cos osiagnac :) |
| Minias | pierwsza metoda zrobienia trypow gry roznej trudnosci zwiazana z doswiadczeniem |
| Minias | to taka, aby za potworka otrzymywac mniej / wiecej expa, zaleznie od wyboru poziomu trudnosci |
18:50 | Minias | aby to zrobic musimy najpierw okreslic tzw. wyjsciowa ilosc doswiadczenia z danego potworka |
| Minias | warto tu zastosowac jakis uniwersalny wzor |
| Minias | u nas bedzie to |
| Minias | exp = (a * 2) / Poziom_Trudnosci; |
| Minias | gdzie 'a' to nasza wyjsciowa ilosc doswiadczenia podana przez nas |
18:51 | Minias | jest to fragment konstruktora potworkow |
| Minias | wiec zmienna typu integer 'exp' jest opatrzona wskaznikiem 'this' |
| Minias | wspominalem o tym wczesniej |
| Minias | wyjasnil to takze MeMeK, o tutaj |
| Minias | http://wyklady.net/logi/cpp_oop_memek.html |
| Minias | ;> |
| Minias | w praktyce wyglada to np. tak: |
| Minias | http://wyklady.net/minias/dev04.cpp |
18:52 | Minias | w sumie wyglada to na dobry sposob dopasowania zdobywanej ilosci doswiadczenia |
| Minias | ale czasem lepszym rozwiazaniem moze byc zrobienie roznych wzorow |
| Minias | dla roznych poziomow trudnosci czyli |
| Minias | najpierw sprawdzamy jaki poziom trudnosci jest ustalony |
| Minias | kiedy to juz wiemy, uzywamy odpowiedni wzor |
| Minias | ilustruje to listing 5 |
| Minias | http://wyklady.net/minias/dev05.cpp |
18:53 | Minias | w sumie jedyna zmiana w porownaniu do listingu 4 |
| Minias | to zawartosc konstruktora Monsterkow |
| Minias | Monster::Monster(char *name, int max, int e) |
| Minias | { |
| Minias | strcpy(tName, name); |
| Minias | maxHP = max; |
| Minias | nowHP = max; |
| Minias | if(trudnosc == 1) |
| Minias | { |
| Minias | exp = e * 4; |
| Minias | } |
| Minias | else if(trudnosc == 2) |
| Minias | { |
| Minias | exp = e * 2; |
| Minias | } |
| Minias | else if(trudnosc == 3) |
| Minias | { |
| Minias | exp = e / 2; |
| Minias | } |
| Minias | } |
18:54 | Minias | jak widac sa tu rozne wzory zaleznie od trudnosci |
| Minias | na najlatwiejszym poziomie exp jest 4-krotnie wiekszy |
| Minias | na srednim dwukrotnie, a na trudnym jest dwa razy mniejszy niz podany przez nas |
| Minias | czyli ogolnie jest to, o co nam chodzilo - zroznicowanie poziomow |
| Minias | w sumie trudno powiedziec ktory sposob warto uzywac (uniwersalny lub osobny) |
18:55 | Minias | ja powiedzialbym, ze wzor uniwersalny warto wykorzystac gdy chcemy osiagnac mala roznice pomiedzy poziomami trudnosci |
| Minias | jesli zas chcemy by przepasc pomiedzy trudnosciami byla wieksza - powinnismy zainteresowac sie indywidualnymi wzorami |
| Minias | i w sumie to wszystko jesli chodzi o doswiadczenie z potworkow |
18:56 | Minias | ale nasza przygoda z experience jeszcze sie nie zakonczyla |
| Minias | :) |
| Minias | potrafimy zrobic juz zroznicowanie jesli chodzi o bezposrednio otrzymywanie doswiadczenie z potworkow |
| Minias | ale to nie wszystko |
| Minias | Pora opracowac metode, dzieki ktorej zaleznie od poziomu trudnosci wymagana bedzie wieksza liczba doswiadczenia |
| Minias | aby uzyskac nastepny poziom |
18:57 | Minias | i tu w sumie takze mozna zrobic uniwersalny wzor lub osobne dla kazdego poziomu trudnosci |
| Minias | ja przedstawie tu tylko rozwiazanie z tym pierwszym, osobne wzory sa analogiczne jak w poprzednim przykladzie |
18:58 | Minias | no wiec chodzi nam o to by na niszym (latwiejszym) poziomie trudnosci wymagane bylo mniej expa |
| Minias | a na wyzszym (trudniejszym) wiecej aby osiagnac nastepny lvl |
| Minias | wlasciwie jest tu podobnie jak z doswiadczeniem z potworkow |
| Minias | tyle tylko ze tu bedziemy dzielic |
| Minias | http://wyklady.net/minias/dev06.cpp |
| Minias | metoda dzialania jest prosta - w strukturze Gracza znajduja sie dwie zmienne zwiazane z expem: |
18:59 | Minias | - pierwsza (allExp) pokazuje ile zdobylismy doswiadczenia do tej pory |
| Minias | - druga (expToLvl) pokazuje ile nam jeszcze brakuje doswiadczenia do nastepnego lvl |
| Minias | kiedy otrzymujemy jakies doswiadczenie, ilosc expToLvl sie zmniejsza podczas gdy allExp = zwieksza sie |
| Minias | a nasz uniwersalny wzor to: |
19:00 | Minias | expToLvl = (lvl + 20) * Monster::trudnosc; |
| Minias | niestety jak pewnie zauwazyliscie podpatrujac kod zrodlowy - jest pewien problem |
| Minias | a mianowicie, kiedy otrzymamy doswiadczenie i przekroczy ono iloc potrzebnego nam do next lvl |
| Minias | to nie przechodzi ono do nastepnego naliczania |
19:01 | Minias | niby nic, ale kiedy przejdzie nam na nastepna kolejke 50000expa i przez to przepadnie - mozna sie wkurzyc;> |
| Minias | oczywiscie i na to jest sposob. Wystarczy zmienic ponizszy fragment: |
| Minias | cout << target.tName << " zabity :D!\n" << "Otrzymales " << target.exp << " doswiadczenia\n"; |
| Minias | allExp += target.exp; |
| Minias | expToLvl -= target.exp; |
| Minias | if(expToLvl <= 0) |
| Minias | { awans(); |
| Minias | } |
| Minias | else cout << "Do nastepnego lvl brakuje Ci jeszcze " << expToLvl << endl; |
| Minias | nizej przykladowe rozwiazanie problemu |
| Minias | (nalezy tylko zrobic tak, by funkcja Gracz::awans() przyjmowala wartosc int) |
19:02 | Minias | np. Gracz::awans(int nadwyzka); |
| Minias | cout << target.tName << " zabity :D!\n" << "Otrzymales " << target.exp << " doswiadczenia\n"; |
| Minias | allExp += target.exp; |
| Minias | expToLvl -= target.exp; |
| Minias | if(expToLvl < 0) |
| Minias | { int a; a = +expToLvl; awans(a); |
| Minias | } |
| Minias | if(expToLvl = 0) |
| Minias | { awans(0); |
| Minias | i zawartosc funkcji Gracz::awans: |
| Minias | } |
| Minias | else cout << "Do nastepnego lvl brakuje Ci jeszcze " << expToLvl << endl; |
| Minias | void Gracz::awans(int nadwyzka) |
| Minias | { cout << "Osiagnales nastepny poziom doswiadczenia!\n"; lvl++; expToLvl = (lvl + 20) * Monster::trudnosc; expToLvl -= nadwyzka; allExp += nadwyzka; |
| Minias | } |
19:03 | Minias | i koniec problemu ze zmarnowanym doswiadczeniem :) |
| Minias | wyjasnie tylko co oznacza linijka 'a = +expToLvl' |
| Minias | otoz jest to zmiana znaku zmiennej expToLvl na dodatni |
| Minias | bo to oczywiste, ze skoro jest mniejsze od 0 to jest minusowe. A my chcemy ja na plusie ;> |
19:04 | Minias | pytania?:P |
| Minias | no to jedziemy dalej |
| Minias | teraz zabawimy sie ze statystykami |
| Minias | jak wczesniej wspomnialem w grach rpg wystepuja statystyki |
| Minias | takie jak sila, zrecznosc, inteligencja, zywotnosc itd |
19:05 | Minias | otoz kolejna zabawa z poziomem trudnosci polega na tym |
| Minias | ze zmieniamy ilosc otrzymywania pkt do rozdzielenia na wybrane statystyki kiedy otrzymujemy next lvl |
19:06 | Minias | otrzymujemy ich wiecej lub mniej, zaleznie od trudnosci |
| Minias | osobiscie nie polecam tego sposobu zroznicowania |
| Minias | statystyki powinno sie zawsze otrzymywac w takiej samej ilosci ;> |
| Minias | ale opisac nie zaszkodzi:) |
19:07 | Minias | jesli ktos sie zdecyduje uzyc tego sposobu, to nie polecam takze uniwersalnych sposobow na ilosc pkt statystyk |
| Minias | lepiej dla kazdego z poziomow trudnosci ustalic osobny wzor |
| Minias | oto przyklad |
| Minias | http://wyklady.net/minias/dev07.cpp |
| Minias | to poprzedni kod ze zmieniona funkcja Gracz::awans |
| Minias | void Gracz::awans(int nadwyzka) |
| Minias | { cout << "Osiagnales nastepny poziom doswiadczenia!\n"; lvl++; expToLvl = (lvl + 20) * Monster::trudnosc; expToLvl -= nadwyzka; allExp += nadwyzka; if(Monster::trudnosc == 1) { |
19:08 | Minias | stats += 10; |
| Minias | } |
| Minias | else if(Monster::trudnosc == 2) |
| Minias | { |
| Minias | stats += 8; |
| Minias | } |
| Minias | else if(Monster::trudnosc == 3) |
| Minias | { |
| Minias | stats += 5; |
| Minias | } |
| Minias | } |
| Minias | (ech rozlazlo sie) |
19:09 | Minias | jak widac (albo i nie widac;/) zaleznie od poziomu trudnosci otrzymujemy konkretnie okreslona ilosc punktow |
| Minias | do rozdzielenia na statystyki |
| Minias | natknelismy sie tutaj na statystyki. W powyzszym przykladzie nie robilismy z nimi nic szczegolnego |
| Minias | nic od nich nie zalezalo |
| Minias | baa, nawet nie istnialy ;> |
19:10 | Minias | pora naprawic nasz (moj;p?) blad. Na poczatku zmodyfikujmy strukture Gracza: |
| Minias | struct Gracz |
| Minias | { |
| Minias | int tObr, |
| Minias | allExp, |
| Minias | expToLvl, |
| Minias | lvl, |
| Minias | stats, |
| Minias | sila, |
| Minias | zywotnosc, |
| Minias | nowHP, |
| Minias | maxHP; |
| Minias | Gracz(int obr); |
| Minias | bool atak(Monster &target); |
| Minias | void awans(int nadwyzka); |
| Minias | }; |
| Minias | dodalismy dwie statystyki na potrzeby wykladu |
| Minias | tj sila i zrecznosc |
19:11 | Minias | wystarcza nam, aby zaprezentowac jak nadac im jakas wazna role :) |
| Minias | spojrzmy na nasz konstruktor |
| Minias | Gracz::Gracz(int obr) |
| Minias | { tObr = obr; allExp = 0; lvl = 0; expToLvl = ((lvl + 2) * 5) * Monster::trudnosc; |
| Minias | } |
| Minias | nas juz to nie zadowala |
| Minias | po pierwsze nie ma tu zadnej wzmianki o sile czy zrecznosci |
| Minias | zywotnosci* |
19:12 | Minias | a po drugie nie odpowiada nam juz wzor |
| Minias | tObr = obr; |
| Minias | zmienmy wiec troszke konstruktor: |
| Minias | Gracz::Gracz(int obr) |
| Minias | { |
| Minias | stats = 5; |
| Minias | while(stats > 0) |
| Minias | { |
| Minias | char znak; |
| Minias | cin >> znak; |
| Minias | if(znak == 's') |
| Minias | { |
| Minias | sila++; |
| Minias | stats--; |
| Minias | } |
19:13 | Minias | else if(znak == 'z') |
| Minias | { |
| Minias | zywotnosc++; |
| Minias | stats--; |
| Minias | } |
| Minias | } |
| Minias | tObr = obr + sila; |
| Minias | maxHP = 30 + (zywotnosc * 2); |
| Minias | nowHP = maxHP; |
| Minias | allExp = 0; |
| Minias | lvl = 0; |
| Minias | expToLvl = ((lvl + 2) * 5) * Monster::trudnosc; |
| Minias | } |
| Minias | jak widzimy jest tu juz przedstawiona pewna rola sily i zywotnosci:) |
| Minias | nalezy takze zmienic Gracz::awans: |
| Minias | void Gracz::awans(int nadwyzka) |
| Minias | { cout << "Osiagnales nastepny poziom doswiadczenia!\n"; |
| Minias | lvl++; |
| Minias | expToLvl = (lvl + 20) * Monster::trudnosc; |
| Minias | expToLvl -= nadwyzka; |
| Minias | allExp += nadwyzka; |
| Minias | if(Monster::trudnosc == 1) |
| Minias | { |
19:14 | Minias | stats += 10; |
| Minias | } |
| Minias | else if(Monster::trudnosc == 2) |
| Minias | { |
| Minias | stats += 8; |
| Minias | } |
| Minias | else if(Monster::trudnosc == 3) |
| Minias | { |
| Minias | stats += 5; |
| Minias | } |
| Minias | while(stats > 0) |
| Minias | { |
| Minias | char znak; |
| Minias | cin >> znak; |
| Minias | if(znak == 's') |
| Minias | { |
| Minias | sila++; |
| Minias | stats--; |
| Minias | } |
| Minias | else if(znak == 'z') |
| Minias | { |
| Minias | zywotnosc++; |
| Minias | stats--; |
| Minias | } |
19:15 | Minias | } |
| Minias | tObr += sila + lvl; |
| Minias | maxHP += 5 * zywotnosc; |
| Minias | nowHP = maxHP; |
| Minias | } |
| Minias | najpierw dodajemy punkty do rodzielenia kiedy otrzymamy next lvl |
| Minias | (zaleznie od poziomu trudnosci jest ich wiecej lub mniej) |
| Minias | a pozniej je rozdajemy, dopoki je mamy :) |
| Minias | nastepnie ponownie okreslamy wartosc tObr |
| Minias | i maxHP |
| Minias | i to tyle jesli chodzi o zabawe ze statystykami |
| Minias | ale powtarzam to, co nadmienilem na poczatku: |
| Minias | nie polecam tego sposobu zroznicowania poziomow |
19:16 | Minias | dam jeszcze malutka podpowiedz odnosnie statystyk |
| Minias | bo w powyzszym przykladzie pominalem kwestie np. zrecznosci |
| Minias | otoz gdyby ktos chcial w swej grze dodac 'zrecznosc' i chcialby, aby odpowiadala ona za czestotliwosc (szybkosc) atakow |
| Minias | to zaprezentuje tutaj przykladowe rozwiazanie tego problemu |
19:17 | Minias | mianowicie |
| Minias | mozna to zrobic za pomoca funkcji Sleep() - Windows |
| Minias | lub sleep() - Linuks |
| Minias | przyklad uzycia: |
| Minias | #include <iostream> |
| Minias | |
| Minias | #ifdef __unix__ #include <unistd.h> |
| Minias | #else |
| Minias | #include <windows.h> |
| Minias | #endif |
| Minias | |
| Minias | using namespace std; |
| Minias | |
| Minias | int main() |
| Minias | { |
| Minias | cout << "a"; |
| Minias | #ifndef __unix__ |
| Minias | Sleep(1000); |
19:18 | Minias | #else sleep(1000); |
| Minias | #endif |
| Minias | cout << "b"; |
| Minias | system("pause"); |
| Minias | return 0; |
| Minias | |
| Minias | } |
| Minias | wartosc funkcji sleep (Sleep) to milisekundy |
| Minias | przypominam ze 1000 msek = 1 sek |
| Minias | mozna wprowadzic do niej takze zrecznosc np. tak |
| Minias | sleep(czaspoczatkowy - (zrecznosc * 10)); |
19:19 | Minias | gdzie czas poczatkowy to czestotliwosc ataku na poczatku rozgrywki ;> |
| Minias | no dobra, ale to tylko taki dodatek dla zainteresowanych :) |
| Minias | pytania jakies? |
| Minias | :> |
| Minias | no dobrze |
19:20 | Minias | to teraz zajmijmy sie czyms prostszym;> |
| Minias | otoz od zawsze wiadomo, ze to, co napedza gry z gatunku rpg to zadania poboczne |
| Minias | (odtad bede je po prostu nazywal jako "questy") |
| Minias | no wiec ta swoboda w grach rpg jest esencja ich zycia:) |
| Minias | odpuscic sobie glowny watek i poniesc sie tej plochej przygodzie - questom :> |
19:21 | Minias | raz jest tak, ze za questy dostajemy doswiadczenie - a raz, ze nie - ze dostajemy tylko jakas materialna nagrode |
| Minias | bron lub zloto, nevermind :) |
| Minias | i tu dochodzimy do kwestii ktora chcialem omowic a mianowicie |
| Minias | zaleznie od poziomu trudnosci po wykonaniu questu zyskujemy doswiadczenie lub nie |
19:22 | Minias | ilustruje to obrazek 5 |
| Minias | |
| Minias | w sumie to dosc proste: |
| Minias | - na poziomie trudnym (3) nie otrzymujemy doswiadczenia po wykonaniu questu |
| Minias | - na poziomie latwnym (1) otrzymujemy doswiadczenie po wykonaniu questu |
| Minias | - a na poziomie normalnym (2).. no wlasnie, kto zgadnie co?;> |
19:23 | Minias | otoz to zalezy od naszego ogolnego(!) zalozenia co do gry |
| Minias | jesli chcemy, by nieotrzymywanie doswiadczenia bylo utrudnieniem na poziomie trudnym |
| Minias | to na poziomie normalnym powinnismy je otrzymywac |
| Minias | natomiast jesli doswiadczenie z questow ma byc milym dodatkiem na najlatwiejszym poziomie |
| Minias | to na poziomie normalnym otrzymywac go nie powinnismy |
19:24 | Minias | mam nadzieje ze to jasne bo oto przyklad tego drugiego rozwiazania: |
| Minias | http://wyklady.net/minias/dev08.cpp |
| Minias | wszystko zalezy od zmiennej statycznej struktury Quest - tzn "static bool exp;" |
| Minias | jezeli jej wartosc to true (prawda) to otrzymujemy doswiadczenie |
| Minias | a jezeli false (falsz), to go nie otrzymujemy |
19:25 | Minias | w sumie otrzymywanie w tym przykladzie czegokolwiek to fikcja |
| Minias | bo doswiadczenie przekazywane jest nam tylko poprzez funkcje 'cout' |
| Minias | i nic innego nie mozemy z nim zrobic |
| Minias | zeby to dzialalo poprawnie musielibysmy dodac strukture gracza i rozwiazac to podobnie jak w przykladzie 7 |
| Minias | ale to juz zostawie Wam, bo to proste i na pewno Wam sie uda to polaczyc;> |
19:26 | Minias | "Item tNagroda" to nagroda materialna, ktora mozemy dostac za quest |
| Minias | wspomniana wczesniej bron czy zloto:) |
| Minias | mysle ze nie ma z questami zadnych niejasnosci |
19:27 | Minias | wiec pominmy zdejmowanie opcji moderate ;> |
| Minias | jak ktos ma pytania to na priv prosze:) |
| Minias | no wiec |
| Minias | wrocmy ponownie do potworkow :) |
| Minias | tym razem zainteresujmy sie potworkami i ich stuffem |
| Minias | a mianowicie, kiedy wreszcie uda nam sie takiego gnojka zabic |
| Minias | to zwykle zrzucaja z siebie jakies przedmioty |
19:28 | Minias | Przy odrobinie szczescia mozna sie niezle oblowic |
| Minias | No wlasnie. Przy odrobinie szczescia |
| Minias | a te odrobine szczescia mozemy regulowac za pomoca poziomu trudnosci |
| Minias | tzn im latwiejszym poziom, tym wieksza szansa ze z potworka wypadna itemki |
| Minias | i to jest naszym aktualnym tematem |
| Minias | http://wyklady.net/minias/dev09.cpp |
19:29 | Minias | wszystko znow jest zalezne od wzoru |
| Minias | u nas jest to |
| Minias | DM.iSzansa = ((5 + DM.iWartosc * Monster::trudnosc) / 2); |
| Minias | ale takze od warunku |
| Minias | if((a >= 5) && (a <= 10)) |
19:30 | Minias | to kazdy moze dopasowac do swoich indywidualnych potrzeb |
| Minias | w kazdym razie w powyzszym przykladzie przy konstrukcji obiektu typu Monster |
| Minias | dobieramy mu jeden przedmiot typu Item. |
| Minias | oczywiscie moglibysmy mu dodac wiecej tych przedmiotow robiac np. w strukturze potworkow |
| Minias | tablice obiektow Item - jeden na helm, inny na bron itd. |
19:31 | Minias | ten przedmiot to rzecz, ktora moze wypasc z potworka jesli dany warunek jest spelniony |
| Minias | szansa przedmiotu: "im mniejsza, tym wieksza!" :D |
| Minias | albo inaczej: im mniejsza, tym latwiej go zdobyc ;> |
| Minias | i w ten sposob osiagnelismy co chcielismy :) |
| Minias | pytania? |
19:32 | Minias | no dobra, wiec lecimy dalej |
19:33 | Minias | pewnie kazdy z Was podczas milych podrozy po krainach swiata gier rpg |
| Minias | natrafil na rozne, ciekawsze lub mniej, skrzynie beczki i rozne pojemniki |
| Minias | w ktorych znajdowaly sie przedmioty o duzej lub malej wartosci |
| Minias | w czesci grach te dane (tzn co w danej skrzyni sie znajduje) sa zawsze takie same |
19:34 | Minias | ale w innych zawartosc skrzyn jest losowa |
| Minias | i dochodzimy do sedna sprawy. Losowosc zawartosci. Co do dla nas znaczy? |
| Minias | a no tyle, ze zaleznie od poziomu trudnosci mozemy wylosowac lepsza lub troszke gorsza zawartosc skrzyni:) |
| Minias | okreslenie lepsza lub gorsza tyczy sie oczywiscie wartosci danego przedmiotu;) |
19:35 | Minias | i w sumie tyle teoria |
| Minias | teraz gorsze pytanie: JAK to zrobic? :> |
| Minias | na poczatku musimy stworzyc klase (strukture;p) pojemnikow |
| Minias | oto ona |
| Minias | struct Pojemnik |
| Minias | { static int Pojemnik::trudnosc; int wspX, wspY, wspZ; Item inside[2]; Pojemnik(int X, int Y, int Z); void zawartosc(Item mozliwosci[]); |
| Minias | }; |
19:36 | Minias | (wybaczcie ze sie rozlazlo, pozniej bedziecie mieli do wgladu czytelniejszy kod) |
| Minias | w strukturze pojemnikow nie ma zadnej nazwy |
| Minias | identyfikowac skrzynie bedziemy tylko po wspolrzednych |
19:37 | Minias | "Item inside[2]" to tablica obiektow typu Item |
| Minias | jak widac sklada sie ona z 2 indexow |
| Minias | w naszym przykladzie w skrzyni znajdowac sie beda 2 rzeczy :) |
19:38 | Minias | Przenieslismy tutaj zmienna trudnosc, gdyz struktura monsterkow nie jest nam w tym przykladzie potrzebna - na smietnik z nia!:P |
| Minias | stworzmy teraz kilka itemkow (zalozmy, 4) |
| Minias | Item przedmioty[4]; |
| Minias | strcpy(przedmioty[0].name, "Morgenstern"); |
| Minias | przedmioty[0].iWartosc = 30; |
| Minias | przedmioty[0].iSzansa = ((5 + przedmioty[0].iWartosc * Pojemnik::trudnosc) / 2); |
19:39 | Minias | |
| Minias | strcpy(przedmioty[1].name, "Miecz"); |
| Minias | przedmioty[1].iWartosc = 40; |
| Minias | przedmioty[1].iSzansa = ((5 + przedmioty[1].iWartosc * Pojemnik::trudnosc) / 2); |
| Minias | |
| Minias | strcpy(przedmioty[2].name, "Topor"); |
| Minias | przedmioty[2].iWartosc = 60; |
| Minias | przedmioty[2].iSzansa = ((5 + przedmioty[2].iWartosc * Pojemnik::trudnosc) / 2); |
| Minias | |
| Minias | strcpy(przedmioty[3].name, "Rozdzka"); |
| Minias | przedmioty[3].iWartosc = 100; |
| Minias | przedmioty[3].iSzansa = ((5 + przedmioty[3].iWartosc * Pojemnik::trudnosc) / 2); |
| Minias | nasze itemki :) |
| Minias | teraz musimy wylosowac dwie z nich - ale w taki sposob, by na mniejszych poziomach trudnosci losowac te lepsze |
| Minias | a na trudniejszych te gorsze |
| Minias | oto rozwiazanie: |
19:40 | Minias | http://wyklady.net/minias/dev10.cpp |
| Minias | cala tajemnica twki w funkcji void Pojemnik::zawartosc(Item tItem[]) |
| Minias | kod jest dlugi, ale nie skomplikowany |
| Minias | mysle ze sami zrozumiecie o co w nim chodzi ;) |
19:41 | Minias | ja chce zwrocic Wasza uwage na inna rzecz |
| Minias | ze w strukturze Itemkow jest zmienna typu bool - 'cenny' |
| Minias | okresla ona, czy przedmiot jest cenny czy tez nie jest |
| Minias | (w naszym przypadku jest cenny gdy jego wartosc wynosi ponad 50) |
19:42 | Minias | a gdy jest cenny - to nie moze sie znalezc w skrzyni na najtrudniejszym poziomie |
| Minias | na poczatku dodajemy takze do inside[0] i inside[1] pojemnika wzmianke, ze te miejsca sa puste |
19:43 | Minias | gdybysmy tego nie zrobili - i nie wylosowalibysmy na to miejsce zadnego przedmiotu |
| Minias | wyswietlilyby sie smieci |
| Minias | lepiej wyglada slowo 'puste' niz jakies znaczki :> |
| Minias | oczywiscie zdaje sobie sprawe, ze przeciez nasz "skrypt" moze uznac nawet slowo 'puste' za jakis item |
19:44 | Minias | mozemy jednak to naprawic |
| Minias | if(!((inside[0].name == "puste") || (inside[1].name == "puste") |
| Minias | { Player::bierz(); |
| Minias | } |
| Minias | ale funkcje bierz() bedziecie juz musieli opracowac sami ;> |
| Minias | a moze innym razem wspomne o tym przy okazji;) |
| Minias | no to moze tym razem sa pytania? :) |
19:46 | Minias | no to lecimy dalej |
| Minias | w sumie teraz omowie cos co troche wykracza poza temat wykladu |
| Minias | ale mysle ze warto to wyjasnic :) |
19:47 | Minias | mam na mysli klonowanie potworkow |
| Minias | (spotykania tych samych gatunkow wiele razy) |
| Minias | chodzi oczywiscie o tablice obiektow typu Monster: ) |
| Minias | jesli to dla kogos nie jest jasne, to niech spojrzy na listing 11 |
| Minias | http://wyklady.net/minias/dev11.cpp |
19:48 | Minias | mysle ze tu pytan nie ma to i oszczedzimy sobie zdejmowanie opcji moderate ;> |
| Minias | zreszta dzis nie jestescie zbyt pytajacy :) |
| Minias | ale jak ktos ma pytanie to na priv prosze :> |
| Minias | no to przejdzmy do czegos blizszego tematu tego wykladu |
| Minias | omowilismy juz wiele zagadnien zwiazanych z grami RPG |
| Minias | ale co z shooterami? |
19:49 | Minias | no powiedzmy, ze wlasnie do nich przechodzimy :) |
| Minias | w sumie nie bedzie to tak rozbudowane jak poprzednie kwestie, ale zawsze cos:) |
| Minias | pierwsza kwestia to apteczki |
| Minias | zwykle po pewnym odcinku na kazdej planszy mozemy natknac sie na apteczki |
19:50 | Minias | i tutaj rola poziomow trudnosci: w zaleznosci od poziomu trudnosci znajdujemy wiecej lub mniej apteczek na swej drodze |
| Minias | przy okazji wykorzystamy tutaj nowo nabyta umiejetnosc klonowania - tym razem apteczek:) |
| Minias | zdefiniujmy strukture Apteczka |
| Minias | struct Apteczka |
| Minias | { |
| Minias | static int trudnosc; |
| Minias | int wsplX, |
| Minias | wsplY, |
| Minias | wsplZ, |
| Minias | ileHp; |
| Minias | bool istnienie; |
| Minias | void regeneracja(); |
| Minias | }; |
19:51 | Minias | zmienna 'istnienie' ustala czy apteczka istnieje czy tez nie. Jest to wymagane przez metode ktora my wybralismy |
| Minias | 'ileHp' okresla, ile dana apteczka regeneruje nam pkt zycia:) |
| Minias | w sumie to takze moglby okreslac poziom trudnosci |
| Minias | http://wyklady.net/minias/dev12.cpp |
| Minias | oto przykladowy kod zwiazany z apteczkami |
19:52 | Minias | widzimy, ze im latwiejszy poziom trudnosci tym wiecej apteczek ma ustawiona zmienna 'istnienie' na true |
| Minias | czyli wiecej apteczek znajdujemy na swej drodze:) |
| Minias | Apteczka zadziala, gdy gracz bedzie stal na tych samych wspolrzednych (w powyzszym kodzie juz tego nie ma) |
| Minias | analogicznie postepujemy z amunicja, ktora mozna znalezc po drodze: |
| Minias | http://wyklady.net/minias/dev13.cpp |
| Minias | cos jest niejasne?:) |
19:53 | garus | jak narazie wszystko ok :D |
19:54 | Minias | tak.. wiec omowmy kwestie wspolna gier rpg i strzelanek;> |
| Minias | no bo wiadomo, przemierzajac swiat i w rpg, i w shooterach, natykamy sie na hordy potworkow |
| Minias | i w ten niepozorny temat znow wciska sie nam poziom trudnosc ;) |
| Minias | trudnosci* |
| Minias | czyli |
| Minias | w zaleznosci od ustalonego poziomu trudnosci spotykamy wiecej / mniej przeciwnikow |
19:55 | Minias | ilustruje to rys.6 |
| Minias | |
| Minias | wlasciwie mozna to rozwiazac praktycznie tak samo jak z apteczkami / amunicja |
| Minias | wiec mysle ze rozpisywanie sie na ten temat jest zbedne ;) |
19:56 | Minias | no i w sumie to tyle jesli chodzi o dzisiejszy wyklad, tzn tyle bylo w planach |
| Minias | mysle ze nie warto juz przedluzac, zreszta i tak skonczyly mi sie pomysly:P |
| Minias | tak wiec nie zapomnijcie ocenic i skomentowac wykladu |
| Minias | http://forum.wyklady.net/index.php?topic=82.0 |
| Minias | jednoczesnie niesmialo zapowiadam, ze byc moze poprowadze drugi wyklad o game developingu;> |
| Minias | niesmialo;> |
| Minias | dobra, dzieki wszystkim:) |
| Minias | koniec :) |