Raycaster-pelimoottori 1: Alkuvalmistelut ja pelitila
Joillekin ei riitä kaksi ulottuvuutta. Tai akselia. Tai suuntaa. Miten vain. Mutta ei minullekaan, eli uteliaisuus vei voiton ja pakotti selvittämään, taipuuko Allegro-kirjasto "kolmiulotteisen", ns. raycaster-pelimoottorin sujuvaan pyörittämiseen. Taipuihan se, tosin Lode Vandevennen raycaster-tutoriaalin ja ChatGPT:n isolla avustuksella. Koodataanpa siis raycaster-pelimoottori!
Raycaster on simppelein mahdollinen FPS-pelimoottori, sillä vaikka näkymä on pelaajan silmistä eli ensimmäisestä persoonasta, kaikki liike tapahtuu kahdella akselilla, eli X:llä ja Y:llä. Z-akselin puuttuessa pystysuuntaista liikettä ei siis ole ollenkaan, eikä kentissä ole korkeuseroja. Lisäksi kentät rakennetaan samanlaisella ruudukolla kuin aiemmin tekemässämme tasohyppelypelissä, eli kentät koostuvat ikään kuin isoista Minecraft-palikoista. 90-luvun raycaster-pelit halusivatkin nimiinsä usein taikakoodin 3-D tai 3D, mikä on klassinen mainosihmisten keino väittää tuotteen olevan jotain, mitä se ei ole. Täydestä meni esimerkiksi tapauksissa Nitemare 3-D (1994), Super 3D Noah's Ark (1994) sekä tietysti Wolfenstein 3-D (1992).
| Super 3D Noah's Ark. |
| Nitemare 3-D. |
| Wolfenstein 3-D. |
Alkuvalmistelut
Ihan ensimmäiseksi, jos et vielä ole pystyttänyt kehitysympäristöä, tee se seuraavien postausten ohjeilla:
Tasohyppelypelin tapauksessa työstimme vain kahta tiedostoa:
main.c-lähdekooditiedostoa sekä main.h-otsikkotiedostoa. Tulevaan
projektiin tulee kuitenkin sen verran paljon koodia, että se kannattaa jakaa
useampaan lähdikooditiedostoon.
Tässä postauksessa valmistellaan siis uusi, "kolmiulotteinen" pelimoottoriprojekti. Luo seuraavat lähdekoodi- ja otsikkotiedostot:
- draw.c ja draw.h
- Näihin lisätään kaikki grafiikan piirtämiseen liittyvät funktiot.
- globals.h
- Tähän lisätään kaikki globaalit muuttujat eli ne, joiden arvoja tarvitaan useammassa lähdekooditiedostossa.
- main.c
- Tähän tulee globaalien muuttujien alustukset sekä ohjelman varsinainen suoritettava funktio main.
- player.c ja player.h
- Näihin lisätään kaikki pelaajan toimintaan liittyvät funktiot.
- setup.c ja setup.h
- Näihin lisätään kaikki ohjelman ja pelitilan alustamiseen liittyvät funktiot.
- types.h
- Tähän lisätään kaikki tietuemuuttujat.
- utils.c ja utils.h.
- Näihin lisätään kaikenlaisia apufunktioita.
Tällaista määrää tiedostoja on aika mälsä kääntää aiemmin käyttämällämme gcc-komennolla ja sen parametreilla. Jotta homma helpottuisi, luodaan batch-tiedosto, jonka sisälle lisätään varsinainen gcc-komento parametreineen. Tällöin ohjelmaa käännettäessä riittää, kun DOSissa kirjoitetaan vain batch-tiedoston nimi ja suoritetaan se.
- Avaa tekstieditorissa uusi tiedosto ja lisää siihen seuraavat rivit:@echo offgcc main.c utils.c draw.c player.c setup.c -o game.exe -lalleg
- Tallenna tiedosto nimellä build.bat samaan sijaintiin luomasi lähdekoodi- ja otsikkotiedostojen kanssa.
- Nyt, kun DOSissa suoritetaan komento build, ohjelma käännetään GAME.EXE-tiedostoksi.
Seuraavaksi lisätään kuhunkin otsikkotiedostoon rivit #ifndef, #define sekä #endif, jotta kaikki otsikkotiedostoon määritellyt vakiot ja muuttujat sekä esitellyt funktiot sisällytetään lähdekooditiedostoon vain kerran.
Lisää siis draw.h-otsikkotiedostoon seuraavat rivit:
Lisää globals.h-otsikkotiedostoon seuraavat rivit:
Lisää player.h-otsikkotiedostoon seuraavat rivit:
Lisää setup.h-otsikkotiedostoon seuraavat rivit:
Lisää types.h-otsikkotiedostoon seuraavat rivit:
Lisää utils.h-otsikkotiedostoon seuraavat rivit:
Pelitila
Seuraavaksi tehdään minimilisäykset, jotta voimme varmistua, että lähdekoodi- ja otsikkotiedostosekoilu kääntyy suoritettavaksi ohjelmaksi ja näyttää pelitilan niin kuin pitää. Tässä pelimoottoriprojektissa työskennellään pelkästään pelitilan parissa, ilman alkuvalikkoa, sillä raycaster-moottorin koodia tulee niin paljon, että on parasta vain keskittyä olennaiseen. Pelkkä pelitila tarkoittaa siis sitä, että kun ohjelma käynnistetään, ollaan suoraan pelitilassa, ja ESC-näppäimellä sammutetaan ohjelma.
Globals.h
Tässä otsikkotiedostossa määritellään ohjelman globaalit vakiot ja muuttujat.
- SCREEN_WIDTH ja SCREEN_HEIGHT määrittävät ruudun resoluution: 320 × 240 pikseliä.
- VIEW3D_HEIGHT on 3D-näkymän korkeus: 200 pikseliä. Näytön alareunaan luodaan siis 40 pikseliä paksu palkki, jossa näytetään pelaajan terveys, ammukset ja muu tärkeä data; ihan niin kuin vanhoissa kunnon 3D-räiskinnöissä.
- 3D-näkymän korkeus voi tietysti olla sama kuin näytönkin korkeus, jolloin palkkia ei luoda. Tällöin HUD koodataan näkymään 3D-näkymän päällä, kuten kaikissa moderneissa 3D-räiskinnöissä.
- FRAMERATE määrittää pelin tavoitekuvataajuuden (30 kuvaa sekunnissa).
- thCounter on globaali, volatile-tyyppinen muuttuja, jota käytetään pelin päivityssilmukassa.
- buffer on BITMAP-tyyppinen osoitin, joka viittaa grafiikkabufferiin.
Nämä määrittelyt varmistavat, että ohjelman kaikki tiedostot voivat käyttää samoja globaaleja muuttujia.
Draw.h
Lisää draw.h-otsikkotiedostoon esittely DrawGame-funktiolle, joka huolehtii pelin grafiikan piirtämisestä.
Draw.c
Lisää draw.c-lähdekooditiedoston määrittely DrawGame-funktio, jossa:
- tyhjennetään grafiikkabufferi (clear_to_color ) ja asetetaan sen taustaväriksi tummanharmaa (makecol(47, 47, 47)).
- kopioidaan grafiikkabufferin sisältö näytölle (blit).
Setup.h
Lisää setup.h-otsikkotiedostoon esittely kahdelle funktiolle:
- TimerHandler käsittelee ajastimen keskeytyksiä.
- SetupProgram alustaa peliohjelman ympäristön.
Setup.c
Lisää setup.c-lähdekooditiedostoon TimerHandler-, ja SetupProgram-funktioiden määrittely.
Main.c
Tee seuraavat lisäykset main.c-lähdekooditiedostoon.
Nyt, kun suoritat DOSissa komennon build, koodi käännetään ja koostetaan suoritettavaksi tiedostoksi GAME.EXE (jos siis kirjoittamassasi koodissa ei ole virheitä). Suorita sitten GAME.EXE, ja ruudulle pitäisi aueta alla oleva näkymä, joka on siis luomamme pelitila.
Kommentit
Lähetä kommentti