Olisiko jollakin jotain ideaa miten voisin tehdä pelimoottorin tekstiseikkailu peliin?
Tai pientä vihjettä... ;)
http://en.wikipedia.org/wiki/Keyboard_
http://en.wikipedia.org/wiki/Vim_(text_editor)
http://en.wikipedia.org/wiki/
http://www.cplusplus.com/doc/tutorial/
Siinä pientä vihjettä. Noita käyttämällä voisit tehdä pelimoottorin. Vaihtoehtoisesti voisit kertoa mikä on ongelma jne. ;)
Ei ohjelmointi ole mikään salatiede, jossa tarvitset guruilta mystisiä loitsuja tuon tekemiseen. Tarvitset riittävät pohjatiedot, ja loput sinun täytyy itse keksiä.
Mieti ensin paperilla, miltä tekstiseikkailu näyttää. Yleensä siinä on erilaisia tiloja ja siirtymiä niiden välillä. Tilanteet ja vaihtoehdot muodostavat verkon, jossa joka tilanne sisältää eri vaihtoehtoja, jotka johtavat uusiin tilanteisiin. Vaihtoehdot voivat sisältää tiedon siitä, mitä siirtymiseen vaaditaan, ja tilanteet voivat sisältää jonkin esineen saamisen tai menettämisen.
Piirrä tätä rakennetta käyttäen vaikka paperille pieni peli. Kirjaa jokaiseen tilaan selostus tilanteesta ja vaihtoehtojen numerot. Kirjaa jokaiseen vaihtoehtoon sen nimi, tarvittavat esineet, tilanne valinnan onnistuttua ja tilanne, jos ehdot eivät toteutuneet. Rupea sitten miettimään ohjelmointitoteutusta. Hyvä lähtökohta voisi olla struct
-sanan eli tietueiden opettelu. Sen jälkeen voisit kehittää tietueen tilanteelle, vaihtoehdolle ja henkilölle (tavaroita ja muita ominaisuuksia varten).
Muista lähteä liikkeelle riittävän yksinkertaisesta!
Kiitos neuvvoista... alan kehittämään sitä pelimoottoria heti... :)
EDIT:
Muutta noissahan ohjeissa on pelkkää perus c++?
EDIT||:
Saisiko noit ohjeita suomeksi? ;)
Niin? C++:llahan se ohjelmoidaan. Ja jos tuo ohje ei aukea, niin luepa ensin vähän lisää perusasioita. Pienikin projekti on iso, jos on mitään epäselvää perusasioissa.
Mulla on toi opas jo. eli mä siis pärjään noilla neuvoilla? No hyvä...
Edit:
Eikös class ole noihin juttuihin kuin struct?
vehkis91 kirjoitti:
Eikös class ole noihin juttuihin kuin struct?
Class ja struct ovat muuten samat paitsi, että class:in jäsenet ovat oletuksena yksityisiä, kun taas struct:in jäsenet ovat oletuksena julkisia.
Eli:
class Nimi { public: jotain };
on sama kuin
struct Nimi { jotain };
ok, mutt eikö ole hyvä, jos osan saa privateks?
Kyllä.
olisikon tästä johonkin: http://vehkis.100free.com/content/main.html ?
NEUVVOJA!!!
Sanoisin, että oikea lähestymistapa tekstipelimoottoriin on se, että varsinainen pelidata eli pelin tilanteet, valinnat ja siirtymät tilasta toiseen on tallennettu tiedostoon (tai muistiin), josta moottori lukee niitä sitä mukaa, kun pelissä edetään. Moottorin ideahan on siinä, että se toimii ytimenä, jonka ympärille itse peli rakentuu. Jos jatkat edelliseen tapaan, siitä ei synny moottoria, vaan yksittäinen peli, jossa kaikki toiminnallisuus joudutaan kirjoittamaan uudelleen jokaisen tilan kohdalla. Tietysti yksittäisellä pelillä on hyvä aloittaa ennen moottorin koodaamista, mutta tapa kutsua aina uutta funktiota on edelleen väärä, koska niistä ei milloinkaan poistuta. Jossain vaiheessa pinomuisti täyttyy yhä uusista kutsuista ja ohjelma kaatuu.
Edit: Eli ellet sitten aio yrittää sitä moottoria, en keksi näin äkkiä kuin yhden ratkaisun, joka on käyttää funktioiden sijaan gotoa. Ohjelmoinnissa yleensä gotoa ei suositella, mutta tekstipelin tilasiirtymärakenteessa se on minusta varsin pätevä.
Haluaisn tehdä moottorin , mutta en osaa, eikä ole harmainta aavistusstakaan miten se tehdään...
Tietty voit yrittää sellaista lähteä väsäämään täältä saaduilla tiedoilla ja googlettamalla, mutta voisit myös vielä kerrata perusteet ja harjoitella joillakin pikkuohjelmilla(niin tylsältä kuin se kuulostaakaan).
Putkalaisten kristallipallotkin tuntuvat olevan niin usein huollossa(omani mukaan lukien), joten on vaikea lähteä selittämään kohtakohdalta mien pelimoottorin rakentaminen onnistuu ;). Toki apua saa pyytää ja Putka onkin melko aloittelijaystävällinen foorumi, joka nykyään interneteissä on aika harvinainen tuttavuus.
Korostan myös paperille suunnittelun merkitystä, mikä selkeyttää ohjelman rakennetta. Kannattaa myös tehdä pieniä sivuprojekteja, joissa kokeilet esimerkiksi tekstitiedoston lukemista, minkä jälkeen voit liittää sen itse peliin.
Ei se moottorin koodaaminen ihan mahdoton juttu ole, mutta voithan aluksi jatkaa tekstiseikkailua ilman moottoria, ja jos siltä tuntuu, koodaat moottorin vasta myöhemmin vaikkapa uuteen projektiin.
Tein jo yhden tekstiseikkailun ilman moottoria, mutta tekisin mielummin mootttorin kanssa. Osaan kyllä liittää tiedoston ifstream ja ofstream käskyillä...
Aluksi sinun on kehitettävä yksinkertainen skriptikieli, jolla tekstiseikkalu voidaan kuvata. Sitten voit tehdä moottorin, joka tulkitsee skriptiä rivi riviltä. Yksinkertaistettuna skripti voisi näyttää esim. tältä:
[tila1] t Peli alkaa. Mitäs teet? v tila2 Tee jotain v tila3 Älä tee mitään v tila4 Lopeta [tila2] t Teit jotain ... [tila3] t Et tehnyt mitään ... [tila4] l
Tässä esimerkissä jokaisella tilalla on tunnus, joka ilmaistaan hakasulkujen [] sisällä. Merkkiä t seuraa teksti, joka kyseisessä tilassa tulostetaan. Kirjaimella v kuvataan valintaa, v:n jälkeen annetaan ensin tila, johon valinnasta siirrytään ja sitten teksti, joka valinnan kohdalla näytetään. Kirjain l merkitsee lopetusta. Näin yksinkertaisella skriptillä ei kuitenkaan saavuteta paljonkaan etuja, sillä sen kanssa joudutaan näkemään lähes sama vaiva, kuin jos pelin raakakoodaisi suoraan jollain ohjelmointikielellä. Yksinkertaisesta on kuitenkin hyvä aloittaa. Kokeile, saatko aikaan ohjelmaan, joka tulkitsee tämän tapaista kieltä, kysy apua tarvittaessa.
ok yritän...
Edit:
Nuo [] jutut tulevat siis tekstitiedostoon?
Jos tulevat, niin uskon pystyväni sen tekemään...
vehkis91 kirjoitti:
Nuo [] jutut tulevat siis tekstitiedostoon?
Kyllä, moottori sitten lukee tuon skriptin tiedostosta ja tulkitsee sen. Huomaathan, että antamani skripti on vain esimerkki. On sinänsä yhdentekevää, millä tavoin skriptissä merkitään mistä tila alkaa tai miten tulostetaan tekstiä, kunhan vain moottorisi tuntee merkintätavan ja osaa tulkita sitä.
Hih, nostalgiaa. Siinä on mallia moottorista. :)
Ehän noissa saa oikeesti käyttää goto... ;)
Edit:
Taidan muokata hieman tuota pelimoottoria...
Mutta käytän silti tota skripti kieltä, se on hyvä...
No tässä on nyt vähän muokattu versio:
*** TextGameEngine.cpp #include <iostream.h> #include <stdio.h> #include <stdlib.h> int juttu,himo,wamma,korpi; FILE *f=NULL; char Buffer[200]; int Loppu(); int Alku(); int Lapi(); int Alku() { fseek(f,0,SEEK_SET); while (fgets(Buffer,200,f)) { himo = atoi(Buffer); for (juttu=0;juttu<himo;juttu++) { fgets(Buffer,200,f); cout << Buffer; } fgets(Buffer,200,f); himo = atoi(Buffer); fgets(Buffer,200,f); wamma = atoi(Buffer); for (juttu=0;juttu<himo;juttu++) { fgets(Buffer,200,f); cout << (juttu+1) << ". " << Buffer; } korpi = -1; while(!(korpi >= 1 && korpi <= himo)) { cout<<endl; cout << "Valintani on: "; cin >> korpi; } for (juttu=0;juttu<himo;juttu++) { fgets(Buffer,200,f); if (korpi==(juttu+1)) cout << Buffer; } cout << endl << endl; if (korpi != wamma) Loppu(); } Lapi(); } int Lapi() { fclose(f); cout << "VOITIT...........! :-o :-o" << endl; return(0); } int Loppu() { cout << "Kuolit!!" << endl; cout<<endl; cout<<"1 ==> Aloittaa alusta."<<endl; cout<<"2 ==> Lopettaa..."<<endl; cin >> juttu; if (juttu==5) Alku(); fclose(f); return(1); } int main(int argc, char *argv[]) { f = fopen(argv[1],"r"); if (!f) { cout << "tiedostoa ei ole." << endl; return(1); } Alku(); return EXIT_SUCCESS; }
Eihän tolla scripti kielellä voi tehdä kovin monimutkaisia pelejä...
Voisiko joku ehdottaa jotain muokkauksia siihen...
Pitäisi pystyä tekemään ainakin 2 tai 3 jatkuvaa vaihtoehtoa...
esim. Mene paikasta a paikkaan b tai paikasta c paikkaan d...
Nyt kun yrittää tota, niin engine lopettaa toisen vaihtoehdon "suorittamisen".
Tuolla tekniikalla homma ei onnistu. Kätevin tapa lienee lukea koko seikkailu muistiin ja pyörittää sitä siellä. Tällöin ei tarvitse kikkailla tiedostojen kanssa.
Esimerkki yhden tilanteen tietueista c++:lla:
struct Valinta { string teksti; // Valinnan teksti int tilanne; // Seuraavan tilanteen indexi }; struct Tilanne { vector<string> kuvaus; // Tilanteen kuvaus vector<Valinta> valinnat; // Mahdolliset valinnat };
Sitten luot tilanteista vectorin ja luet tilanteet niihin. Skriptikielen saat kehittää ihan itse — vähän muokkaat alkuperäistä.
vector<Tilanne> tilanteet; // Tämä sitten sisältää ne tilanteet, helppo käyttää.
Jos string tai vector eivät ole tuttuja, ne voi toki korvata taulukoilla, mutta suosittelen käyttämään c++:n ominaisuuksia ihan oman mielenterveytesi takia.
Kannattaa miettiä toteutusta ensin itse kunnolla. Jos ei miettimällä selviä, niin sitten vain kyselemään lisää neuvoja :)
No en ole vectoreita pahemin käyttäny, mutta kerta se on ensimmäinenkin... ;)
Kiitos neuvoista!!!
Edit:
Saisiko sitä vectori ohjetta jostain suomeksi?
Samaisesta oppaasta jonka Markus aijemmin tuolla jo linkitti.
http://www.nic.funet.fi/c opas/stl.html
Tai sitten näyttäis löytyvän useampiakin sivustoja ja PDF dokumentteja esimerkiksi
http://www.oamk.fi/~jjauhiai/opetus/olio/stl07.
Miksi dev-c++ 4.9.9.2 ei tunnista string käskyä????!!!
Kai muistit otsikkotiedoston
#include <string>
string on määritelty std-nimiavaruudessa. Toisin sanoen, jokin näistä kolmesta:
using namespace std; // Otetaan koko std-nimiavaruus käyttöön(otsikoiden jälkeen) using std::string; // Otetaan vain string-käyttöön(otsikoiden jälkeen) std::string teksti; // "Viitataan suoraan nimiavaruuteen"
Ja sama homma sitten vectoreiden kanssa.
mullon
#include <string> using namespace std;
Eikä toimi...
No millaisen virheilmoituksen se antaa? Anna koko litanja.
Edit:
Hups
Unohdin ton namespacen...
EDIT:::
Miten luen sen koko tiedoston muistiin ja sen jälkeen vasta katson tietyn osan siitä?
Miks musta tuntuu että sä et mieti yhtään itse vaan kyselet koko ajan täältä apua?? Yritä itse vähän miettiä ja tutkiskella ennen kuin kysyt täältä mitään!
Noi vectori on kyllä kauheen epä selviä, ainakin http://www.nic.funet.fi/c opas/stl.html tossa oppaassa...
Taidan käyttää taulukoita...
Ellei sitten jotain huvita neuvoa mulle tota vectorin käyttöö... ;)
Tarkoitatko muuten tolla "muistiin lukemisella", että se luetaan tiedostosta muistiin? (Luultavasti Kyllä, mutta haluan olla varma)
vehkis91 kirjoitti:
Ellei sitten jotain huvita neuvoa mulle tota vectorin käyttöö... ;)
int luku = 0; // luodaan int tyyppinen vektori vector<int> taulukko; // vrt. int taulukko[]; // lisätään taulukon perään alkioita taulukko.push_back(luku); // muuttujasta taulukko.push_back(7); // paljas luku(literaali) taulukko.push_back(luku+3); // lasku... // lisätään ensimmäisen ja toisen alkion väliin alkio(arvo luku-muuttujasta) taulukko.insert(taulukko.begin()+1, luku); // muokataan alkioiden arvoja .at() ja [] ovat vaihtoehtoisia taulukko[0] = 4; taulukko.at(2) = luku; // tulostetaan alkioiden arvot (.size() kertoo vektorin alkioiden määrän) for(unsigned int i = 0; i < taulukko.size(); ++i) { // molemmilla tavoilla cout << taulukko[i] << " " << taulukko.at(i) << endl; } // poistetaan keskimmäinen alkio taulukko.erase(taulukko.begin()+1); // poistetaan viimeinen alkio taulukko.pop_back(); // Muutetaan vektori olemaan kymmenen alkion kokoinen. Uudet alkiot alustetaan nollaksi taulukko.resize(10, 0); // nyt voidaan syöttää arvoja suoraan taulukko[9] = luku; taulukko.at(5) = 713; // Tyhjennetään vectori taulukko.clear(); // Tarkastetaan, onko vectori tyhjä if(taulukko.empty()) { cout << "tyhjä"; }
Toivottavasti ei tullu pahoja virheitä. Jos ilmenee ongelmia, niin kysy.
Edit: Eli vektorit ovat dynaamisia taulukoita ja ne hoitavat muistin varaamisen itse. Lisäksi ne sisältävät kaikenlaisia hyödyllisiä lisäkilkkeitä.
vehkis91 kirjoitti:
Tarkoitatko muuten tolla "muistiin lukemisella", että se luetaan tiedostosta muistiin? (Luultavasti Kyllä, mutta haluan olla varma)
Kyllä. Eli luet tiedoston sisällön vaikkapa edellä ehdottamiini tietueisiin.
Kyllä tuo varmaan onnistuu, mutta en keksinyt, miten voin lukea tiedot tiedostosta suoraan vectoriin...
ifstream f; f.open("testi.txt", ios::in); //miten tästä eteenpäin????
Jos ei kerta suoraan lukeminen onnistu, niin miksi et tekisi sitä mutkan kautta? Kannattaa aina miettiä, osaanko toteuttaa sen edes jollain tapaa.
vector<string> kuvaus; string rivi; // Apumuuttuja ifstream tiedosto; tiedosto.open("testi.txt", ios::in); // Luetaan rivinvaihtoon asti ja lisätään luettu rivi vektoriin getline(tiedosto, rivi); kuvaus.push_back(rivi); f.close();
Tiedoston saa luettua stringiksi virtapuskureiden (?) avulla.
#include <sstream> #include <fstream> // ... std::ostringstream apuvirta; std::ifstream tiedosto("tiedosto.txt"); apuvirta << tiedosto.rdbuf(); std::string tiedoston_sisalto = apuvirta.str();
Jos tiedosto taas on lista välilyönnein erotettuja sanoja tai numeroita, niin lukemisen voi tehdä suoraan virtaiteraattoreilla:
#include <iterator> #include <fstream> #include <vector> // ... // Lukee tiedoston sanat vektoriin std::ifstream tiedosto("tiedosto.txt"); std::vector<std::string> sanavektori( std::istream_iterator<std::string>(tiedosto), // virtaiteraattori tiedostoon std::istream_iterator<std::string>() // "EOF"-virtaiteraattori );
Niin tai näin, merkkijonojen ja tiedostojen käsittely standardi-C++:lla on yhtä tuskaa joka tapauksessa.
Tosiaam tuskaa.. Mutta kun en osaa mitään muutakaan... tai yritän opetella vb:tä...
Käykö jos mulla on näin:
#include <iterator> #include <fstream> #include <vector> using namespace std; main() { ifstream tiedosto("tiedosto.txt"); vector<string> sanavektori() istream_iterator<string>(tiedosto), // virtaiteraattori tiedostoon istream_iterator<string>() // "EOF"-virtaiteraattori }
toi on vaan esimerkki...
Minusta on alkanut tuntua, että tällä lähestymistavalla engine etenee juuri siihen tahtiin, kuin minä ja muut sitä tänne jaksavat kirjoitella. Muutamme siis lähestymistapaa!
Otat kynän, paperia ja kumin. Sitten kirjoitat tarkat vaatimukset enginelle ja skriptikielen syntaksin. Tämän jälkeen aloitat suunnittelemaan ohjelman toteutusta yleisellä tasolla. Ensimmäiselle paperille voisi tulla vaikka ohjelman funktioiden kutsukaavio ja lyhyt kuvaus kustakin funktiosta. Koska kukaan tuskin tekee sinulle näitä funktioita valmiiksi, täytyy niidenkin toteutus suunnitella. Siispä lisää paperia ja suunnitellaan tarvittavien funktioiden toteutus sillä tarkkuudella, että pystyt toteuttamaan sen c++ koodina. Loppuvaiheessa funktioiden kuvaukset voivat olla hyvinkin lähellä pseudokoodia, mutta tämä ei ole välttämättömyys. Kuitenkin, mitä lähempänä pseudokoodia suunnitelma on, sitä herkemmin virheet ja puutteet havaitsee. Lisäksi yksi tärkeimmistä suunnittelun kohteista ovat tietorakenteet, joihin tallennat ohjelmasi tarvitsemat tiedot. Tämä kannattaakin suunnitella heti alkumetreillä niin ei tarvitse jälkikäteen muutella funktioiden toteutuksia.
Ja mitä viimeisimpään kysymykseesi tulee, kyllä käy, mutta en ymmärrä mitä hyötyä tuosta on. Olet lukenut tiedoston string-tyyppiseen vectoriin. Tilanne on mielestäni vastaava, kuin olisit kopioinut koneesi kiintolevyltä tietoa usb-tikulle. Tieto ei siis juurikaan ole helpommin käsiteltävissä. Se pitäisi vielä järjestää johonkin järkevään tietorakenteeseen.
Älä kuitenkaan lannistu. Sinulla tuntuu olevan motivaatiota enemmän, kuin suurimmalla samantyyppisien ongelmien kanssa taistelevilla :)
Tee vaikka pääpiirteittäinen suunnitelma enginen toteutuksesta(josta selviää ainakin tietorakenteet, funktioit sekä niiden tarkoitus ja skriptikielen syntaksi) ja lähetä se tänne meidän kommentoitavaksi.
Edit: Näin saat kokonaiskuvan ohjelmastasi ja pystyt miettimään itse, mitä pitää tehdä, minkä takia ja milloin.
No joo pitää tehdä niin...
En oikeen opi kunnola kirjoitsta c++ ja kouluun pääsen joskus 4 vuoden päästä, niin pitää vähän kysellä ku intoa kuitenkin piisaa...
Mutta alan pikkuhiljaa toteuttaa paperille sit engineä ja muuta...
Muuten teenkö siitä jonkun UML kaavion?
vehkis91 kirjoitti:
Muuten teenkö siitä jonkun UML kaavion?
Se on yksi hyvä vaihtoehto. Pääasia on, että siitä saa selkeän käsityksen ohjelman rakenteesta.
okey
Aihe on jo aika vanha, joten et voi enää vastata siihen.