Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Eka peli

Sivun loppuun

Zakki [25.11.2007 15:08:56]

#

Mistä kannattaa aloittaa, jos haluan tehdä jonkun yksinkertasen pelin? Eikä mitään tekstiseikkailuja, koska niitä on tullu tehtyä tarpeeks.

Tzaeru [25.11.2007 15:13:47]

#

SDL:n opettelusta. Opassarja löytyy Oppaat-osiosta.

Tämän jälkeen pohdit vaikka yksinkertainen tileseikkailupeli tulisi toteuttaa, tyyliin Pókemon-sarja Gameboylle. Sitten toteutat ja voilã.

Gaxx [25.11.2007 15:17:37]

#

Ensin kannattaa suunnitella se peli kokonaisuudessaan. Tällöin varmistut siitä, että taitosi riittävät pelin ohjelmointiinkin.

Metabolix [25.11.2007 16:24:54]

#

Kannattaa ottaa selvää asioista, ettei tee samoja tyhmyyksiä kuin tuhat edellistäkin yrittäjää. Suunnittelu ja matematiikan ja yksinkertaisen mekaniikan ymmärtäminen ovat myös tärkeitä, fysiikka ainakin reaaliaikaisissa ja ollenkaan tyylikkäästi tehdyissä peleissä.

Antti Laaksonen [25.11.2007 17:07:17]

#

Jos ohjelmoit C:llä tai C++:lla, tarvitset ensinnäkin jonkin kirjaston, jolla voi ainakin piirtää grafiikkaa ja tarkkailla näppäimistöä. Yksi tällainen kirjasto on SDL, jonka käyttöön Ohjelmointiputkassa on oppaita.

Ensimmäinen tehtävä on yrittää saada valittu kirjasto toimimaan, mikä ei aina ole helppoa. Tämän jälkeen kannattaa tehdä pieniä testiohjelmia, jotta oppii piirtämään kuvia näytölle ja tunnistamaan käyttäjän näppäilyjä. Tästä ei enää olekaan pitkä matka ensimmäiseen peliin.

E.K.Virtanen [25.11.2007 22:06:10]

#

Hieman jos tietäisi mikä on tasosi? Joillekin perus matopelikin on jo iso juttu. Tekstiseikkailua ei kannata tehdä jos sellaista ei halua.

Zakki [26.11.2007 00:21:20]

#

en ole ennen tehnyt grafiikkaa tjms.

T.M. [26.11.2007 00:56:02]

#

Pelin tekoon vaaditaan paljon tietoa ennenkuin siitä saa kunnollista ja toimivaa kokonaisuutta.

Sinun täytyy osata taulukoiden käyttö hyvin, ymmärtää miten niitä voi hyödyntää kaikin mahdollisin keinoin. Eipä siinä sitten tuon lisäksi muuta tarvita kuin ripaus yksinkertaista +-*/ -lasku matikkaa, kunhan muistat vielä välttää aina neliöjuuren käyttöä sen turhuutensa/hitautensa vuoksi. sin/cos voisi vielä opetella että saa tehtyä pyöreitä liikeratoja.

Tämän lisäksi täytyy sinun tietää ohjelmointikielen rajoitukset, esim tietotyyppien koot, muistin varaus oikein, muistin käsittely oikein. Sekä taitoa optimoida tiettyjä vaiheita koodissa nopeammiksi.

Käytännössä katsoen, en suosittele pelin tekemistä jos et osaa yhtään mitään vielä, opettele asiat kunnolla, tee pieniä pelin alkuja, ja sitten lopuksi voitkin yhdistellä aikojen saatossa kerättyä oppia yhdeksi peliksi. Eihän siitä tule kiva mieli jos pitää jokaisen peliin tulevan jutun takia tulla putkan foorumeille kyselemään apua... turhautuu vain.

Zakki [26.11.2007 16:19:06]

#

oon mä tehny yhen aika isonki tekstipelin, koodia oli 602 riviä. http://www.freewebs.com/lacrimosal/newhalpix.cpp

tossa olis varmaankin ollu hyvä, jos olis jotenki voinu noitten funktioiden jutut siellä suluissa minimoida, mut en tiiä miten se tapahtuu, koska noi fungut ei jaa tietoja keskenään ilman niitä.

Kray [26.11.2007 16:56:10]

#

Zakki kirjoitti:

oon mä tehny yhen aika isonki tekstipelin, koodia oli 602 riviä. http://www.freewebs.com/lacrimosal/newhalpix.cpp

tossa olis varmaankin ollu hyvä, jos olis jotenki voinu noitten funktioiden jutut siellä suluissa minimoida, mut en tiiä miten se tapahtuu, koska noi fungut ei jaa tietoja keskenään ilman niitä.

Ihan hyvännäköistä koodia... Oot tehny paljon ratkaisuja joita en ois älynny ite... En osaa kunnolla c++:aa mutta hyvältä näyttää, jos grafiikat otat mukaan niin hyvät mahdollisuudet!

Metabolix [26.11.2007 17:06:43]

#

Suhteellisen asiallinen sisennys, plussaa siitä! Voisit vielä tutustua struct-avainsanaan ja esimerkiksi tuossakin säilyttää tietoja globaalissa muuttujassa. Lisäksi olet tuossa tehnyt sellaisen virheen, että kutsut aina vain uusia funktioita etkä koskaan pääse niistä takaisin. Lopulta koneesta loppuu muisti ja ohjelma kaatuu. Virheitäkin tuossa on, monissa tapauksissa peli nimittäin käyttäytyy hyvin omituisesti. (En kokeillut, mutta kaiken näkee koodista parilla vilkaisulla.)

Nyt seuraa pieni katsaus pelin sisältöön.

Graafista peliä tehdessä kannattaa sisäistää tällainen ajatus pääohjelman rakenteesta:

aika_ennen = -1;

while (1) {
  // Luetaan viestit (napinpainallukset, hiiren liike) ja tarkistetaan, onko esim. rastia painettu
  if (kasittele_viestit() == SAATIIN_LOPETUSVIESTI) {
    break;
  }
  // Ei tullut lopetusviestiä, joten jatketaan
  // Lasketaan edellisestä kierroksesta kulunut aika
  aika_nyt = lue_aika();
  kulunut_aika = aika_nyt - aika_ennen;
  aika_ennen = aika_nyt; // Merkitään aika menneeksi

  // Käsitellään tilanteen mukaan sopivaa asiaa sopivan verran eteenpäin
  switch (tila) {
    case VALIKKO:
      laske_valikon_uusi_tila (kulunut_aika);
      piirra_valikko();
      break;
    case PELI:
      laske_pelin_uusi_tila (kulunut_aika);
      piirra_peli();
      break;
  }
}

Viestinkäsittelyfunktio voi vaikkapa päivittää globaaliin taulukkoon tiedon painetuista näppäimistä ja hiiren sijainnista ja sen nappien tilasta. Valikon uutta tilaa laskettaessa voidaan näistä todeta, että käyttäjä on painanut nuolta alas, joten merkitään alempi kohta valituksi ja otetaan entisestä valintamerkki pois. Valikkoa piirrettäessä katsotaan valikon tiedoista, että kohdassa 1 lukee "Uusi peli" ja se on merkitty valituksi, joten printataan se punaisella, ja kohdassa 2 lukee "Lopeta" ja sitä ei ole merkitty valituksi, joten piirretään se harmaalla.

Silmukka alkaa alusta. Tällä kertaa käyttäjä on painanut enteriä, joten valikon tilan laskuissa katsotaan, mikä kohta oli valittuna, ja merkitään tila-muuttujan uusi arvo sen mukaan, tässä tapauksessa vaikkapa tila = PELI. Lisäksi voidaan kutsua sopivaa alustusfunktiota, jotta pelisilmukka alkaa oikein.

Seuraavilla kierroksilla päädytäänkin käsittelemään pelin tilannetta. Katsotaan, mitä nappeja käyttäjä painaa, ja toimitaan sen mukaan. (Matematiikkaa tarvitaan törmäyksen tunnistamiseen. Suosittelen tässä asiassa oman järjen käyttöä ja itsenäistä opettelua.) Kun jollain kierroksella peli päättyy, kutsutaan tarpeellisia funktioita ja merkitään tilaksi taas valikko.

Toivottavasti tässä nyt pysyi ajatus mukana ja toivottavasti tästä saa jotain irti. :)

viznut [26.11.2007 17:17:42]

#

Ei sitä akateemisen maailman "globaaleja muuttujia pitää välttää" -dogmia sentään ihan NOIN kirjaimellisesti tarvitse ottaa kuin Zakki on pelissään tehnyt :)

L2-K2 [26.11.2007 21:33:33]

#

viznut kirjoitti:

Ei sitä akateemisen maailman "globaaleja muuttujia pitää välttää" -dogmia sentään ihan NOIN kirjaimellisesti tarvitse ottaa kuin Zakki on pelissään tehnyt :)

Käyttäisi struckteja niin koodi lyhenisi, selkeytyisi ja muuttuisi helpommin päivitettäväksi. Eikä silti tarvittaisi globaaleja muuttujia.

struct
{
    int str;
    int def;
    int end;
    int exp;
    int lvup;
    int lv;
    int hp;
    int maxhp;
    string wpn;
    int wpnd;
    int wpnvalue;
    string arm;
    int armr;
    int armvalue;
    int raha;
    string name;
    int pot5hp;
    int pot20hp;
    int pot40hp;
    int pot65hp;
    int pot95hp;
}hahmo;

// kutsutaan
hahmo pelaaja;

// käytetään
pelaaja.exp; //suora
&pelaaja->exp; // osoittimella

// funktiolle annetaan vain structin osoite *pelaaja

FooBat [26.11.2007 21:37:13]

#

L2-K2 kirjoitti:

viznut kirjoitti:

Ei sitä akateemisen maailman "globaaleja muuttujia pitää välttää" -dogmia sentään ihan NOIN kirjaimellisesti tarvitse ottaa kuin Zakki on pelissään tehnyt :)

Käyttäisi struckteja niin koodi lyhenisi, selkeytyisi ja muuttuisi helpommin päivitettäväksi. Eikä silti tarvittaisi globaaleja muuttujia.

Niin ja koska kyse on C++ koodista niin voisi jopa käyttää sellaisia pelottavia otuksia kuin luokkia.

Zakki [27.11.2007 16:04:30]

#

tein tossa eilen SDL pelin, mitä mieltä ootte?

http://www.freewebs.com/lacrimosal/main.c

http://www.freewebs.com/lacrimosal/boltsman.rar

Kray [27.11.2007 16:09:31]

#

Ei lähe käyntiin, koska ensiksi puuttuu SDL.dll, ja kun kopioin sen sinne, niin valittaa: "Proseduurin aloituskohtaa SDL_strclat ei löydy dynaamisesti linkitettävästä kirjastosta SDL.dll." Onkohan mulla vanhempi versio vai...?

tsuriga [27.11.2007 16:10:49]

#

On varmaanki, koska kävin ite just uuden ja pelitti. Endless fun.

EDIT: Tai mitäpä minä SDL:stä tietäisin, komppasin pohdiskelua.
EDIT2: Taas näen tabeista asiaa, tästähän on väännettävä oikein oma aihio.

Metabolix [27.11.2007 16:16:45]

#

Miksi sisennät koodia noin paljon ja miksi väleillä etkä tabulaattorilla? Mikset käytä erillisiä funktioita ollenkaan? Voisit myös kiinnittää huomiota standardien noudattamiseen. Tuolla ei ole toivoakaan kääntyä C:nä, joten päätteen pitäisi olla jokin C++:aan viittaava, esimerkiksi cpp tai cxx.

Koodissa on oikeastaan pari perustavanlaatuista mokaa. Liikkuminen pitäisi suhteuttaa kuluneeseen aikaan, kuten jo mainitsin. Häviötä on tyhmää tarkastaa neljällä eri ehdolla erikseen, kun häviökoodi on aina sama. Lisäksi ohjelmasta poistumisessa on bugeja. Jos lopetetaan kesken pelin, osa kuvista jää vapauttamatta. Parempi olisi tuossa tilanteessa katkaista silmukka, jolloin siirryttäisiin valmiiseen lopetuskoodiin main-funktion lopussa. Häviötilanteissa unohdat asettaa joku = false, joten peli ei oikeasti lopu häviöön. Toimivuuden harhakuva syntyy siitä, että kukaan ei paina esc-näppäintä niin nopeasti, ettei myös pelisilmukka saisi sitä kiinni ja menisi pelin lopetukseen (rivin 130 ympäristö).

Voisit vielä kokeilla, saatko pelin siirrettyä tuohon yllä selostamaani muottiin. Tulet isommissa projekteissa huomaamaan, että tämänhetkinen ratkaisumallisi ei ole hallittavissa.

Osaat ilmeisesti asiat aika hyvin, mutta ei taida olla takana vielä yhtään niin isoa projektia, että olisi tullut vastaan kysymyksiä järkevästä (vaivattomasta) koodaustyylistä. Mutta ihan sillä tavalla taisi tuo peli sujua, että otahan kolapullo kaapista, pane pitsa jäähtymään ja koodaa jotain isompaa. ;)

TsaTsaTsaa [27.11.2007 16:17:54]

#

Segmentation fault (core dumped)

Zakki [27.11.2007 17:01:16]

#

Metabolix kirjoitti:

Miksi sisennät koodia noin paljon ja miksi väleillä etkä tabulaattorilla? Mikset käytä erillisiä funktioita ollenkaan? Voisit myös kiinnittää huomiota standardien noudattamiseen. Tuolla ei ole toivoakaan kääntyä C:nä, joten päätteen pitäisi olla jokin C++:aan viittaava, esimerkiksi cpp tai cxx.

Tabijutut johtuu Dev-c++:an omasta automaattisesta tabulointisysteemistä. Olen myös tottunut siihen, eli en muuta sitä. Myös tekstitiedoston pääte on Devin käsialaa

Legu [27.11.2007 19:34:52]

#

TsaTsaTsaa, onhan kuvat samassa kansiossa binaarin kanssa? Itselläni siitä tuli segfaulttia, kun niitä ei ollut.

Yhdyn Metabolixin kommenttiin. Tuo tausta.bmp on kyllä sinänsä turha, nimittäin tuon voisi toteuttaa koodissakin.

Rar on huono, älä käytä sitä :)

TsaTsaTsaa [27.11.2007 19:50:59]

#

Legu kirjoitti:

TsaTsaTsaa, onhan kuvat samassa kansiossa binaarin kanssa? Itselläni siitä tuli segfaulttia, kun niitä ei ollut.

Ainiin joo, kuvat :)

Otin vain wgetillä sorsan ja käänsin.

Zakki [28.11.2007 00:06:01]

#

Legu kirjoitti:

TsaTsaTsaa, onhan kuvat samassa kansiossa binaarin kanssa? Itselläni siitä tuli segfaulttia, kun niitä ei ollut.

Yhdyn Metabolixin kommenttiin. Tuo tausta.bmp on kyllä sinänsä turha, nimittäin tuon voisi toteuttaa koodissakin.

Rar on huono, älä käytä sitä :)

Rarissa ei ole mitään vikaa :D

Jos ei sitä taustaa olis laittanu olsi jääny niitten pallojen jälkeen sellanen ärsyttävä jälki. Jos olisin laittanu koko näytön kokosen taustan, se olis lagannu, ainakin lagas ku kokeilin. noi pienet näytöt "pyyhkii" ne jäljet vaa noitten perästä

Legu [28.11.2007 14:36:44]

#

Zakki kirjoitti:

Jos ei sitä taustaa olis laittanu olsi jääny niitten pallojen jälkeen sellanen ärsyttävä jälki. Jos olisin laittanu koko näytön kokosen taustan, se olis lagannu, ainakin lagas ku kokeilin. noi pienet näytöt "pyyhkii" ne jäljet vaa noitten perästä

SDL_FillRect(naytto, NULL, 0);

Tuo laittaa koko pinnan mustaksi, ja se on melko nopea. Eli tuon vaan laitat ennen piirtoa, niin pääset niistä jäljistä ja tausta.bmp:stä.

Zakki [28.11.2007 16:34:26]

#

kiittoss

Janezki [02.12.2007 10:11:41]

#

Pakko herättää tätä aihetta että pääsen kertomaan tragedian mikä aiheutui huonosta projektinhallinnasta ja suunnittelusta. Minulla oli tuossa pari vuotta sitten tosi iso peliprojekti. En suunnitellut ohjelmaa lainkaan vaan lähdin heti rakentamaan corea. Sinällään oikea homma lähteä heti vaikeammasta asiasta liikkeelle, mutta kävi niin ensinnäkin että projekti ylitti minun silloiset ohjelmointitaidot, syntyi spagettia, koodia piti uusia, asioita jättää pois, ja piti tehdä paljon extrahommia. Projekti ei ikinä valmistunut, sillä loppuvaiheissa huomasin että itse peli oli tylsä, liian satunnainen, buginen, liian raskas softamoottorille ja muutenkin huonosti toteutettu. Core oli niin spagetissa että olisi ollut helvetillistä lähteä uusimaan sitä. Nyt koko vuoden kestänyt projekti, yli 2000 riviä koodia, 30 grafiikkatiedostoa ja 3 komponenttia lojuu tuolla hylättyjen projektien kansiossa.

Tarinan opetus: Suunnittele projektit aina loppuun asti.

FooBat [02.12.2007 10:28:36]

#

Janezki kirjoitti:

Tarinan opetus: Suunnittele projektit aina loppuun asti.

Ja luulet, että joku kuuntelee sinua? :)
Jokaisen ohjelmoijan pitää kokea tuo tilanne muutaman kerran ihan omatoimisesti ennen kuin alkaa oikeasti antamaan arvoa suunnittelulle. Mutta oikeasti ei yleensä ole väliä hajoaako ensimmäiset isommat projektit käsiin vai ei. Niissä oppii joka tapauksessa paljon eikä lopputulos onnistuessakaan todennäköisesti olisi kovin kummoinen. Joten siitä vaan kaikki intoa puhkuen koodaamaan ja etsimään osaamisen rajoja! Myöhemmin saattaa tulla eteen tilanne, että olet oppinut ohjelmoimaan ja suunnittelemaan, mutta tiedostat kuinka paljon työtä ja aikaa jonkin ohjelman kunnolla koodaaminen vie, joten et uskalla edes aloittaa projektia. Usein innostuksella ja pienellä tietämättömyydellä pääsee pitkälle.


2000 riviä koodia on muuten aika lähellä yleistä purkkakoodin kriittistä massaa etenkin, jos koodi sijaitsee kokonaan yhdessä tiedostossa ja sitä hallitaan alkeellisella tekstieditoritlla. Hiukan paremmin suunnitelluissa projekteissa 2000 riviä ei toisaalta ole mitään.

Janezki [02.12.2007 14:13:16]

#

FooBat kirjoitti:

2000 riviä koodia on muuten aika lähellä yleistä purkkakoodin kriittistä massaa etenkin, jos koodi sijaitsee kokonaan yhdessä tiedostossa ja sitä hallitaan alkeellisella tekstieditoritlla. Hiukan paremmin suunnitelluissa projekteissa 2000 riviä ei toisaalta ole mitään.

Korjaan n. 3000 riviä 21 yksikössä, ei tyhjiä rivejä. Kävin ihan tarkistamassa.

Niin no olihan se hyvin opettavainen kokemus sinällään. Opin tekemään itsenäisiä olioita, luomaan komponentteja ja asentamaan niitä ide:hen, grafiikkapuolta, muistin hallintaa yms. Mutta olisi siltikin mukavampi jos itse pelikin olisi pelattavassa kunnossa. Ei minusta uusien ohjelmoijien tarvitse kompastua näihin yksinkertaisiin seikkoihin vaikka uusia ovatkin. Projektisuunnittelussa kun ei häviä mitään, paitsi ehkä aikaa, mutta senkin ajan voi menettää koodausvaiheessa jos ei ole suunnitellut huolella. Malttiahan se tietysti vaatii, ja tuo sinun väitös vanhan koodarin pessimismistä taitaa valitettavasti pitää paikkaansa.

Kray [10.12.2007 14:58:17]

#

Zakki kirjoitti:

Myös tekstitiedoston pääte on Devin käsialaa

Ei, se on aivan sinun käsialaasi. Kun Dev-c++:ssa luodaan uusi projekti, sen ikkunan oikeassa alareunassa on valintaboksit joissa on c ja c++, joka määrittelee kielen jota ohjelma olettaa sinun käyttävän.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta