Snake5's Blog

Kāda spēļu veidotāja blogs…

Monthly Archives: jūnijs 2010

Deprogress.. (par spēles sižeta līknēm un dzīvību reģenerēšanos)

Es vēlreiz paspēlēju Gunplay v0.1. Nezinu, kāpēc, daži vārdi laikam bija pieķērušies pie galvas un nelaida vaļā. Izgudroju, ka liela daļa problēmu slēpās health-bar’ā. Un sapratu kaut ko svarīgu par spēles “sižeta līkni”.

Vispirms seko īss rants, tad paskaidrošu. Spēlēs ar dzīvības reģenerēšanos sižeta līkne sūkā. Ne tā sižeta līkne, kas ir stāstam, bet tā, ko rada spēles process katrā līmenī. Smagi sūkā. Tai ir savi pielietojumi – piemēram pasaulēs, kur grūti nokontrolēt galvenā (spēlētāja vadītā) varoņa ievainojumus, bet citur – galīgi neder. Tā ir tik neciešami šausmīga un tā izbojā visu procesu, ka to būtu jāaizliedz ar likumu.

Gan jau lielai daļai cilvēku varētu likties aizdomīgs šāds traks sauciens, ka to varētu nejauši uztvert kā saucienu pēc trakomājas.. 😀 .. bet tā gluži nav. Tagad sekos paskaidrojums manam apgalvojumam (negribu to saukt par teoriju, tad teikums zaudē stiprumu).

Tātad, kā jau teicu, katram līmenim ir sava sižeta līkne. Ja kāds no skolas izgāja ar galvu tik paceltu, ka zināšanas izkrita, atgādināšu – sižeta līkne norāda emocionālo kustību literārajā darbā – kur ir mierīgi momenti, kur momenti liek sirdij lekt no rāmjiem ārā u.tml. Spēlē ir tas pats ar spēles procesu. Ir tāda līkne. Šīs līknes kontrolēšana ir ļoti svarīga, lai visiem spēlētājiem dotu apmēram to pašu iespēju izklaidēties un lai pati izklaide būtu interesantāka. Tāpēc es arī nerespektēju open world spēles – tur gandrīz viss ir atkarīgs no spēlētāja, nav garantijas, ka nav izmests laiks un nauda vējā…

Ar dzīvību reģenerēšanos ir tāda problēma, ka tā pamatīgi nolīdzina sižeta līkni. Padara to gandrīz plakanu. Kas nozīmē – spēles process ir daudz neinteresantāks nekā tas varētu būt. Ja apskatāmies uz spēlētāju reakciju procesā, viss kļūst skaidrs. Šeit ir dažas saīsinātas līknes diezgan savādā rakstā.. 😀

Ar reģenerēšanos: omfg-phew-omfgomfg-phew-omfgomfgomfg-phew. omfg skaits norāda augstumu, phew – noiešanu atpakaļ uz nulles pozīciju.

Bez reģenerēšanās: omfg-phew-omfg-shit-help-damn-one down-shit-damn-almost killed me-phew. phew – noiešana uz 0, one down – viens uzdevums izpildīts, visi pārējie – ceļas vai tiek turēts līmenī satraukums un adrenalīns.

Ja nu ar šo vēl nebija skaidrs, tad mēģināšu izskaidrot vēl citādāk – dzīvību reģenerēšanās ilgi neuztur satraukumu, nerada spriedzi, jo pēc katra uzdevuma notiek atgriešanās uz nulles līmeni, kur spēlētājs ir pavisam mierīgs. Bet mierīgs spēlētājs ir neieinteresēts spēlētājs.

Ja reiz dzīvības reģenerēšanās ir tik šausmīga, tad kāpēc to vispār lieto? Atbilde ir tā pati, kas vienmēr – lētākais veids, kā sasniegt mērķi, t.i. izveidot un sākt tirgot spēli. Tādu procesu ir daudz vienkāršāk veidot, nav jāuztraucas par problēmām, kas var rasties kādā nenostrādātā līmenī, nav pat obligāti jāzīmē health bar… rezultāts, protams, ir neinteresantāka spēle, bet AAA kompānijas tas neinteresē. Daudzi nepamanīs, kas viņus aizrauj vairāk, kas mazāk. Daudzi neievēros sīkās problēmas, kuras traucēja spēlēt. Un tā arī bija, ka mēs neievērojām šo pakāpenisko pāreju uz lēto patērētāju kultūru, kura ir izveidojusies tik šausmīga, ka vemt gribas. Tikai tad, kad ar pirkstu sāk AAA kompānijas bakstīt sejā un prasīt, lai par kvalitatīvu programmatūru maksājam divreiz mazāk nekā par šausmīgu spēli, rodas kaut kāda saprašana par to, kur vispār šī kustība iet. Un dzīvību reģenerēšanās ir tikai viens no neskaitāmajiem kustības blakusproduktiem, no kuriem jātiek vaļā tik strauji, kā no līķa dzīvojamajā istabā… 😀

EDIT: Atcerējos tomēr vienu sakarīgu pielietojumu – spēlēs, kur 1 līmenis ir 1 cīņa. Tur dzīvības reģenerēšanās sistēma strādās arī diezgan labi, jo nav iespējas ilgi uzturēt stresu spēlētājā. Tomēr nereģenerējošā sistēma strādā labāk – kam par pierādījumu kalpo dažādas PS1 spēles.

Traka ideja

Ienāca prātā tāda doma, ka labi var paātrināt darbu pie līmeņu redaktoriem, ja atsakāmies no tā GUI, ko vienmēr esam lietojuši. Ideja ir vienkārša – visas darbības, kuras var veikt UI, jāpārnes uz tīriem rakstīšanas darbiem. Ja mēs atceramies korejiešus, kuri spēlē Starcraft – viņi spēj veikt ļoti daudz darbības minūtē. Mēs nevaram būt tikpat labi, kā viņi, bet mēs varam mācīties, lietojot tādu pašu sistēmu.

Šādi varētu izskatīties mazs darbs 2D līmeņu redaktorā.

Novieto kursoru punktā, kur būs gaisma.
[Ctrl+E] – Parādās entity’u saraksts.
-Var iet cauri sarakstam ar “~” un “-“, līdz atrodas pareizajā daļā un izvēlēties entity’u ar atbilstošo ciparu.
-Var ierakstīt filtru un tad izvēlēties.
-Klaviatūras lietošanas problēmu dēļ, beigās var ievietot pārbaudi – vai izvēlēts pareizais entity.
Pieņemsim, ka gaisma sākumā izskatās galīgi ne tā, kā vajag.
[Ctrl+P] – Parādās regulējamo parametru saraksts.
Parametra izvēle identiska entity’a izvēlei, bet to mazā skaita dēļ var pazust nepieciešamība pēc pārvietošanās uz citām saraksta daļām.
Mums nepatīk gaismas attālums, kurš ir 1. parametrs, mēs to gribam nomainīt: [E], [1]
-Mēs varam arī nezināt, kādu tieši mums viņu vajag, jāizmanto slider’is:
[Ctrl+S], ievada mazāko vērtību (var atstāt default’o), [Enter], ievada lielāko vērtību(<–), [Enter]
To tagad var vilkt ar peli, skatoties, kā viss izskatās.

Tā kā vērtību rakstīšanai neizmanto peli, tad var atvieglot rakstīšanu ar shortcut keys lietošanu.
Piemēram, Left – ievietot pēdējo kaut kur citur ierakstīto vērtību; Up – ievietot default’o vērtību; Right – ievietot šo pašu vērtību no pēdējā entity’a, kur tā modificēta.

Ērtība ir vērtība

Nesen darbā ar Gunplay vajadzēja atjaunot visus Parkour līmeņus. Mēs jau zinām, cik viņu ir daudz… nu ja nezinām, tad – 5 staigājamie, 1 īsfilmas līmenis. Atjaunot = izdzēst nederīgo entity’u, gaismām iedot vērtības, kuru nav (pēc gaismas entity’a uzlabošanas pievienotas 2 vērtības – power un z, no kurām viena varētu nebūt tik svarīga, bet otra gan ir – tā nosaka gaismas stiprumu, ja tā ir 0 vai tās nav, tad gaismas nav). Nu tā es to kādu laiku darīju ar roku. Un bija OK, jo tāpat nevarēja visām gaismām vienādas vērtības dot. Bet ar nemākslinieciski viedotajiem Parkour bija pavisam citādāk – nebija intereses visas gaismas manuāli atjaunot. Tāpēc es pieliku kodā default’o vērtību automātisko ielicēju vietās, kur to nav. Rezultātā nepatērēju nekādu laika daudzumu pie katras gaismas.

It kā jau acīmredzams uzlabojums. Bet man kā programmētājam, kas no seniem laikiem iemācījies, ka ar brute force var izdarīt visu, tas tik ātri neatnāca.. 😀 Tagad jau tikai kaut kā vairāk pierasts optimizēt un domāt par šo visu iepriekš.

Bug’u ciems

Man, kā jau izredzētajam, bieži nākas sastapties ar reti sastopamām problēmām… 😀

Šajā attēlā ir viena interesanta un neredzēta problēma…

Flash in a flash…

Iesāku lietot Flash vienam mazam brīvdienu projektam. Nebiju domājis, ka tik šausmīgi var iznākt tajā kodēt. Nemaz nerunājot par to, ka C++ā es visu izdarītu daudz ātrāk un ērtāk, un smukāk… Flash’am vēl paliek savas problēmas, no kurām pat labs dzinējs nepalīdzēja atkratīties..

http://megaswf.com/serve/13451/

Tas ir tas, ko man izdevās izveidot pēc diezgan ilgas čakarēšanās ar PBE. Te nu ir problēmas, no kurām tikt vaļā neizdevās:

-liekvārdība kodā – Jāraksta tik daudz lieku mēslu, lai iedarbinātu vienkāršu algoritmu. It īpaši vektoru kodā.
-kodēšana caur stiklu – man tiek iedalīts kaut kāds apgrauzts interfeiss, kurš izskatās tik pilns ar iespējām, bet patiesībā gandrīz neko nedara. Kontroles gandrīz nekādas, read-only property’i netiek atzīmēti – tikai kompilētājs mani vairākas reizes manos eksperimentos pataisa par muļķi.. 😀
==nākamie nedaudz vairāk uz dzinēju attiecas varbūt==
-problēmas ar update-draw sistēmu – es uzliku SWF failam 60 fps, bet raustās viss tā, it kā nebūtu ne 60, ne 30, bet sin(time)*10 + 50. Neciešu, ka viss vienkārši nevar nestrādāt.
-pikseļu nobīdes objektiem – iespējams, ka tā ir dzinēja problēma, bet es neticu, ka nekustīgi Box2D ķermeņi (density=0) pēkšņi sāktu kustēties un mainīt pozīciju minimāli, pietam pēc neizprotamiem algoritmiem.
-komponentu sistēma forša, bet normālas piekļuves citu komponentu mainīgajiem nav – vēl trakāk kā skriptu dzinēja piesaistīšanā, jo te nav reāla attaisnojuma tam.

Valoda nevar piemēroties programmētājam, bet programmētājam jāmainās valodas dēļ. Priekš sīkiem projektiem, kuros lielāko daļu var sazīmēt dārgajā Adobe Flash Pro rīkā un atliek tikai primitīvas procedurālas kustības/darbības pielikt – valoda ir normāla. Bet spēlēm – nemaz. Pieredze, protams, izveidotu traku koda bāzi, kuru varētu lietot vēl un vēl, bet darba ātrums ir tik lēns, ka pēc C++ā redzētā vienkārši nav vēlēšanās mainīties.
Un Silverlight solās būt līdzīgs (lai gan pēc C# pētījumiem izskatās, ka vismaz vektori būs lietojami).
Tāpēc izskatās, ka šis varētu būt arī mans pirmais un pēdējais projekts Flash’ā, ja es šo vispār pabeigšu.

Slimo cilvēku intereses

Nesanāca dialogs. Varbūt sanāks monologs. Sakārtošu domas un centīšos visu pateikt tik mierīgi un loģiski, cik tas ir iespējams. Ideja ir apkopot, izanalizēt un piebeigt to sūdu čupu, kas sakrājās šodien. Šeit tiks prezentēts mans viedoklis par situāciju, tāpēc visi, kuriem tas varētu nepatikt, variet sagatavot vemjamos maisiņus pirms lasīšanas. 🙂 Lasīt vairāk par šo ziņu

Galvenā problēma ar AI

Pārskatīju automātiski izveidoto informāciju par pretinieka ceļiem. Galvenā problēma – ceļi pārklājas un neīstajās vietās (uz zemes) veidojas pārāk gari. Otro problēmu viegli salabot, par pirmo vēl jādomā.

Tad vēl ir pretinieka nespēja apstāties ceļa vidū vai arī iet uz ceļa vidu.

Tad vēl kāpšana pa trepēm.

Kad viss šis būs piebeigts, tad varēšu veidot pretinieka uzvedības sistēmu.

Vēl parādījās joki ar animāciju redaktoru GUI labojumu dēļ.

GUI ievietots

Gunplay’ā ieliku jauno GUI. Gandrīz. Vēl tikai galveno izvēlni atjaunot vajag. Viss pārējais strādā lieliski.

Te daži attēli no tā brīža, kad beidzot pēc neskaitāmo kļūdu labošanas viss nokompilējās:

GUI uzlabojumi

Pabeidzu uzlabot GUI. Ir Editbox un ir pārējie sīkumi pabeigti. Tagad tikai atlika nokopēt kodu un integrēt Gunplay’ā.

Te ir redzams Editbox objekts:

Supergļuks

Es tagad, darbam labi iedvesmojies, uzkodēju Editbox’u. Vēl tikai nepieliku iespēju mainīt burtu skatu un vēl burti netiek “apgriezti”, lai neietu pāri malām. Bet citādi – gandrīz kā Windows’ā Editbox. Būs daudz ērtāk ar tādu strādāt.

Bet interesantāk tomēr bija tikt galā ar vienu supergļuku. Centīšos īsumā pastāstīt, kā tad viņš radās un kāpēc, un, protams – kā ar to tiku galā.

Izdarīju dažas šķietami nesvarīgas darbības – pamainīju dažus elementus statiskajā masīvā, salaboju dažas problēmas, utt. Pēkšņi parādās kaut kāds gļuks – std::multimap (kur es glabāju ID->GUI Objekts stilā datus, lai ātri pēc ID sameklētu vajadzīgo objektu) izdzēšoties dara savādus jokus. Mēģināju neuztaisīt nevienu GUI objektu. Tad gļuks pārnesās uz std::vector (GUI objekti, sakārtoti pēc Z un radniecības). Skaidrs bija, ka problēma ir ar atmiņu. Tad nodomāju, ka vaina varētu būt datoram un nodrošināties mēģināju, pārbaudot atmiņu (nedaudz, slinkums bija visu pārbaudīt, dators arī cepās :D). Izskatījās, ka vaina tomēr nav datoram. Atcerējos veco labo joku ar pārrakstīšanu pāri atmiņai. Pirmajā momentā biju domājis, ka tam nevajadzētu radīt problēmu, jo tieši ar tekstu esmu ļoti daudz šādi strādājis un ir pieredze ar pointer’iem mocīt tekstu. Tur kļūdu, protams, arī nebija, kā noskaidroju vēlāk. Bet nu vispirms es izdomāju, ka jāsāk no 1. gui objekta uztaisīšanas.. (visus pārējos atslēdzu, problēma tāpat bija aktīva un konstanta (precīzi tā pati problēma, kas ļāva secināt, ka vaina tomēr ir atmiņas piekļuvē)) ..un jāseko visam, ko dara kods. Tā nu es nonācu līdz vainīgajai vietai minūtes laikā…

Mana GUI sistēma lieto virtuālos key’us (piemēram, KEY_MouseLeft = 1, KEY_Backspace = 4, etc.). Protams, lai ērtāk būtu padot tos pa taisno no notikumu (event) lasīšanas vietas, izveidoju tabulu. Lietoju testam SDL. Izrādījās, ka tur ir dažas atšķirības klaviatūras uztveršanā no Windows’a. Tāpēc ļaušu šo smieklīgo kļūdu demonstrēt attēlam:

Izrādījās, ka SDL API nezināšana maksāja diezgan daudz laika. Tur SDLK_LAST bija 323, kas arī bija pogu skaits. Ne 256, kas ir Windows API vai DirectInput API.

Nobeigumā jāsaka, ka priecājos, ka pietika prāta neatmest šo variantu kā vainīgo, kad gāju pāri visam kodam. Rakstīt kodu rītā (kas nu kuram ir rīts.. :D) ir labi. 🙂