PANEVĖŽIO JUOZO BALČIKONIO GIMNAZIJA Projektinis darbas
Antanas Vasiliauskas IIIf
Augustinas Jarockis IIIe
Vadovė Renata Burbaitė
Panevėžys
2021
Naudojamos programos ir C++ bibliotekos
Projekto paruošimas ir sukonfigūravimas
"Tetris" žaidimo logikos kūrimas
Scenų valdymo sistemos ir meniu kūrimas
Autonominės programos, žaidžiančios žaidimą, kūrimas
Šiais laikais programavimo srityje sparčiai populiarėja įvairūs programinės įrangos kūrimo įrankiai, žymiai spartinantys programuotojo darbą. Dažniausiai šie įrankiai už programuotoją atlieka didžiąją darbo dalį: norint sukurti svetainę, užtenka pasirinkti turinio valdymo sistemos (Wordpress ar kt.) temą ir įdiegti funkcionalumo įskiepius. Norint sukurti žaidimą, galima naudoti žaidimų variklį (ang. Game engine), kuris pasirūpina tokiais dalykais kaip kompiuterinės grafikos vaizdavimu (ang. rendering), žaidimo scenų valdymu (ang. Scene management), laiko parinkimu, kada atnaujinti vaizdo kadrą, registruoti žaidėjo įvesti ir t.t. Šios platformos sutaupo daug laiko ir padeda išvengti nereikalingų rūpesčių programuotojams, tačiau jų naudojimas turi ir neigiamų pusių. Visų pirma, programuotojo įgyjamos žinios naudojantis tokiomis platformomis yra mažiau vertingos. Kadangi jos atlieka didžiąją dalį darbo suteikdamos abstrakcijas, tai programuotojas veikiau išmoksta, kaip dirbti su tomis platformomis, o ne universalių programavimo žinių ir paradigmų, kurias galėtų panaudoti už šių platformų ribų. Šios platformos taip pat gali apriboti programuotoją, kadangi jis naudojasi aplinka, kurią sukūrė kiti žmonės, tad gali kilti problemų bandant išplėsti jos funkcionalumą, norint pridėti į projektą tai, ko platforma nesiūlo. Dažnai nutinka taip, kad programuotojas, užuot galvojęs, kaip išspręsti problemą, galvoja, kur galėtų surasti dar vieną programavimo įrankį ar biblioteką, kuri padarytų darbą už jį.
Šio mūsų projektinio darbo tikslas – atsiriboti nuo tokių platformų ir sukurti visiems gerai žinomą 1984 metų žaidimą „Tetris". Jį kurti C++ programavimo kalba, stengtis naudoti kuo mažiau pagalbinių programų ir parašyti didžiąją dalį programos logikos patiems.
• Sukurti žaidimą be žaidimo variklio ir naudojant kuo mažiau pagalbinių programų.
• Įgyti žinių apie kompiuterinės grafikos, abstrakcijų ir sistemų kūrimą.
• Įgyti žinių dirbant su C++ programavimo kalba.
• Įgyti įgūdžių, kaip tvarkyti ir išlaikyti organizuotą struktūrą didelės apimties projekte.
• Sukurti autonominę programą, galinčią žaisti mūsų sukurtą žaidimą geriau nei žmogus.
Kurdami žaidimą neišsivertėme be šių pagalbinių programų:
pav. 1: Visual Studio
Visual Studio 2017
- Kodo redagavimo įrankis, kuris paryškina C++ kalbos sintaksę ir rodo klaidas.
- Palengvina programos kompiliavimo procesą, tad nereikia pačiam kompiliuoti programos per komandinę eilutę.
pav. 2: GitHub
GitHub
- Leidžia patikimai saugoti skirtingas programos versijas vienoje vietoje.
- Leidžia vienu metu dirbti keliems žmonėms prie to pačio projekto ir vėliau sujungti pakeitimus.
pav. 3: Projekte naudojamos bibliotekos
OpenGL GLEW ir GLFW C++ bibliotekos
-
Suteikia bazines funkcijas, tokias kaip tuščio programos lango sukūrimas, 2D figūrų braižymas nurodant RGB spalvą bei figūros viršūnių koordinates ir pan.
-
Suteikia funkcijas, palengvinančias naudotojo klaviatūros įvesties fiksavimą.
-
stb_image biblioteka leidžianti paveiksliukus paversti tekstūromis.
pav. 4: Grafikos kūrimo programų logotipai
Inkscape ir Pixlr grafikos kūrimo programos
-Suteikia įrankius, leidžiančius sukurti žaidimui naudojamus paveikslėlius.
Visą darbo eigą galima suskirstyti į šiuos mažesnius tikslus, kuriuos teko įvykdyti:
- Projekto paruošimas ir sukonfigūravimas
- Abstrakcijų kūrimas
- "Tetris" žaidimo logikos kūrimas
- Scenų valdymo sistemos ir meniu kūrimas
- Žaidimo gerinimas
- Autonominės programos, žaidžiančios žaidimą, kūrimas
Sukūrę Visual Studio projektą parsisiuntėme ir sukonfigūravome bibliotekas, skirtas darbui su OpenGL: GLFW, GLEW ir stb_image.
pav. 5: Išorinių bibliotekų susiejimas su projektu per Visual Studio
Teisingai sukonfigūravus projektą pavyko sukurti tuščią programos langą:
pav. 6: Sukurtas tuščias programos langas
Taip pat, naudojant bibliotekos funkcijas, nupiešti stačiakampį programos lange:
pav. 7: Programos lange nupiešiamas baltas stačiakampis
Net tokiam paprastam stačiakampiui, kuris pavaizduotas viršuje, nupiešti, prireikia palyginus daug operacijų: deklaruoti masyvą su 8 elementais – stačiakampio kiekvienos viršūnės X ir Y koordinatėmis, nurodyti RGB spalvą ir iškviesti 3 OpenGL bibliotekų suteiktas funkcijas. Akivaizdu, kad norint sukurti ganėtinai kompleksišką žaidimą, kaip „Tetris", reikia supaprastinti kodą, įvesti abstrakcijų. Tai yra, reikia sukurti sistemą, lyg labai primityvų žaidimų variklį, kurį sudaro, atskirų paveiksliukų objektų supaprastintas sukūrimas, automatizuotas jų piešimas ant ekrano, tekstūrų uždėjimas. Šios sistemos sukūrimas leidžia atlikti tam tikrus, gana kompleksiškus darbus, vienos funkcijos iškvietimu. Pagrindinės mūsų sukurtos abstrakcinės funkcijos:
// iš paveiksliuko padaro tekstūrą
int AddTexture(std::stringpath)
// nupiešia kvadratą
int Square(floatx, floaty, floatplotis, floatilgis, inttekstura)
// panaikina kvadratą
void SquareRemove(int square)
Šių funkcijų panaudojimo pavyzdys:
pav. 8: Sukuriamas paveiksliuko objektas su katės tekstūra naudojant abstrakcines funkcijas
Turint viršuje paminėtas abstrakcijas, pagaliau galima pradėti kurti patį žaidimą.
Šis žaidimas – tai begalinis ciklas, kuriame atliekami tam tikri skaičiavimai, o priėjus instrukcijų galą, atnaujinamas vaizdo kadras ir programa „užmiega" 50 milisekundžių naudojant standartinę C++ bibliotekos funkciją, o tada vėl kartoja ciklą:
std::this_thread::sleep_for(std::chrono::milliseconds(50));
Visi skaičiavimai ir žaidimo operacijos, kaip figūros pasukimas, vyksta skaičių kintamuosiuose. Žaidimų laukas, kaladėlių esama vieta, žaidimo greitis ir kiti parametrai apibūdinantys žaidimo būseną taip pat saugomi skaičių kintamuosiuose. Svarbiausias kintamasis – grid[] skaičių masyvas, reprezentuojantis žaidimų lauką. Jo dydis priklauso nuo žaidimo lauko ilgio ir pločio, t.y. grid[ilgis*plotis]. Kas 50 milisekundžių gavus žaidėjo klaviatūros įvestį ir atlikus skaičiavimus, gaunamas galutinis skaičių masyvas grid[], kuris yra išvedamas į ekraną (seni kvadratėliai pašalinami) naudojant viršuje paminėtas abstrakcines funkcijas.
pav. 9: Skaičių masyvas reprezentuojantis žaidimų lauką pav. 10: Skaičių masyvas išvedamas į ekraną naudojant abstrakcines funkcijas
Naudojant šitą techniką, galiausiai sukūrėme pirminę žaidimo versiją.
pav. 12: Skirtingos žaidimo scenos
Žaidimui reikėjo pagrindinio meniu ir žaidimo nustatymų meniu. Meniu veikimo principas labai paprastas: nupiešiama nuotrauka su visu tekstu ir paveiksliukais bei ant pasirinkto mygtuko uždedamas tuščiaviduris stačiakampis – žymeklis. Judinant jį su klaviatūros klavišais sekama, kuris mygtukas yra pažymėtas ir ant jo perkeliamas žymeklis. Paspaudus ENTER atliekama to mygtuko funkcija. Meniu galima sutikti dar dviejų tipų elementus: slankjuostes ir kintamojo užrašo mygtukus. Pastarieji veikia paprastai: ant pradinio paveiksliuko uždedama arba pašalinama vieno žodžio tekstūra. Slankjuostės veikia kitaip: jos padaromos iškerpant plotelį pradinės tekstūros ir už jos uždedant baltą stačiakampį, kuris slankioja į vieną ar kitą pusę. Taip pat yra vienas ypatingas elementas: žaidimo lauko dydžio keitimas. Jis veikia taip: uždedamas paveiksliukas, vaizduojantis visus žaidimo lauko dydžius. Ant jo uždedamas baltas stačiakampis, vaizduojantis dabartinį pasirinktą lauko dydį, ir skaičiukai šonuose, rodantys tikslias jo reikšmes. Pagrindiniame meniu galima pasirinkti eiti į nustatymus, žaisti žaidimą ar išeiti iš programos. Nustatymuose galima išjungti/įjungti garsą, keisti jo dydį, keisti žaidimo figūrų kritimo pradinį ir maksimalų greičius, greitėjimą. Taip pat, galima keisti žaidimo lauko dydį, pašalinti taškų rekordą, pasirinkti, kad žaidimas būtų paleistas pilno ekrano režimu. Taip pat, yra žaidimo įvadas, pasirodantis paleidus žaidimą, kuris pamoko, kaip žaisti.
Turint veikiantį meniu, beliko gerinti patį žaidimą. Visų pirma, pridėjome žaidimui muziką. Tuomet parašėme algoritmą, kuris automatiškai pakeistų visų elementų dydį ir išcentruotų žaidimų lauką, kad žaidėjas galėtų pasirinkti, kokį nori žaidimo lauko dydį, net ir 1000x1000.
pav. 13: Skirtingų dydžių žaidimo laukai
Galiausiai, naudodamiesi grafikos kūrimo įrankiais padarėme geresnes žaidimo tekstūras: skirtingų spalvų kvadratėlius, žaidimų lauko linijas ir foną. Žaidimas dabar atrodo taip:
pav. 14: Pagerintos žaidimo grafikos
pav. 15: Robotas Samuolis
Autonominės programos, žaidžiančios žaidimą, kūrimas
Susipažinkite su robotu Samuoliu:
Samuolio egzistencijos tikslas – žaisti kuo geriau arba kuo blogiau žaidimą „Tetris", priklausomai nuo nuotaikos. Jo veikimo principas gana paprastas: pagal mūsų sukurtą algoritmą yra įvertinama kiekviena įmanoma pozicija, kur galima pastatyti dabar valdomą figūrą. Pasirenkama ta pozicija, kuri surenka daugiausiai (arba mažiausiai) taškų. Algoritmas skiria arba atima taškus iš pozicijos pagal tokius kriterijus:
• Kuo žemiau pastatoma figūra, tuo ėjimas geresnis.
• Kuo mažiau tarpų paliekama po figūra, tuo ėjimas geresnis.
• Kuo daugiau linijų sunaikinama pastačius figūrą, tuo ėjimas geresnis.
pav. 16: Į komandinę eilutę išspausdinami duomenys apie roboto pasirinktą ėjimą
Algoritmas, naudojantis šiuos ir kitus paprastus kriterijus, sugeba žaisti vidutiniškai geriau, negu žmogus.
Žaidime šiuo metu nėra kai kurių funkcijų, esančių moderniose ir profesionaliose tetrio versijose: figūros kol kas parenkamos visiškai atsitiktinai, tai sukuria situacijų, kai pralaimima tiesiog dėl atsitiktinumo. Taip pat, neįmanoma vienu metu sudėti daugiau nei keturių eilučių, kai tuo tarpu profesionaliose versijose galima ir dvidešimt. Be to, nors žaidimas atrodo neblogai, jo tekstūras būtų galima pagražinti.
Pavyko sukurti žaidimą be žaidimo variklio. Supratome, kad tai yra ilgas, varginantis, tačiau įdomus procesas. Kurdami žaidimą patobulėjome ir daug ko išmokome:
- Patobulinome savo programavimo ir darbo komandoje įgūdžius.
- Įgijome žinių apie kompiuterinės grafikos, abstrakcijų ir sistemų kūrimą.
- Išmokome tvarkyti ir organizuoti didelės apimties projekto struktūrą.
Ateityje žadame neapleisti žaidimų kūrimo, kurti kitus, originalesnius žaidimus. Darydami šį projektą įgijome naudingos patirties, padėsiančios ateityje.