Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Pelimoottori (C++)

Sivun loppuun

vehkis91 [28.01.2008 21:25:54]

#

Olisiko jollakin jotain ideaa miten voisin tehdä pelimoottorin tekstiseikkailu peliin?

Tai pientä vihjettä... ;)

jcd3nton [28.01.2008 22:06:26]

#

http://en.wikipedia.org/wiki/Keyboard_(computing)
http://en.wikipedia.org/wiki/Vim_(text_editor)
http://en.wikipedia.org/wiki/GNU_Compiler_Collection
http://www.cplusplus.com/doc/tutorial/

Siinä pientä vihjettä. Noita käyttämällä voisit tehdä pelimoottorin. Vaihtoehtoisesti voisit kertoa mikä on ongelma jne. ;)

Metabolix [28.01.2008 23:00:47]

#

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!

vehkis91 [29.01.2008 12:32:47]

#

Kiitos neuvvoista... alan kehittämään sitä pelimoottoria heti... :)


EDIT:
Muutta noissahan ohjeissa on pelkkää perus c++?

EDIT||:
Saisiko noit ohjeita suomeksi? ;)

Metabolix [29.01.2008 13:14:07]

#

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.

Markus [29.01.2008 13:16:24]

#

vehkis91 kirjoitti:

Saisiko noit ohjeita suomeksi? ;)

http://www.nic.funet.fi/c opas/

vehkis91 [29.01.2008 13:28:18]

#

Mulla on toi opas jo. eli mä siis pärjään noilla neuvoilla? No hyvä...


Edit:
Eikös class ole noihin juttuihin kuin struct?

Markus [29.01.2008 15:34:49]

#

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 };

vehkis91 [29.01.2008 15:43:05]

#

ok, mutt eikö ole hyvä, jos osan saa privateks?

TsaTsaTsaa [29.01.2008 16:10:21]

#

Kyllä.

vehkis91 [29.01.2008 16:54:42]

#

olisikon tästä johonkin: http://vehkis.100free.com/content/main.html ?

NEUVVOJA!!!

hunajavohveli [29.01.2008 18:37:07]

#

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ä.

vehkis91 [29.01.2008 21:17:20]

#

Haluaisn tehdä moottorin , mutta en osaa, eikä ole harmainta aavistusstakaan miten se tehdään...

Mobel [29.01.2008 23:55:57]

#

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.

vehkis91 [30.01.2008 16:15:43]

#

Tein jo yhden tekstiseikkailun ilman moottoria, mutta tekisin mielummin mootttorin kanssa. Osaan kyllä liittää tiedoston ifstream ja ofstream käskyillä...

hunajavohveli [30.01.2008 18:01:38]

#

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.

vehkis91 [30.01.2008 20:08:05]

#

ok yritän...


Edit:
Nuo [] jutut tulevat siis tekstitiedostoon?

Jos tulevat, niin uskon pystyväni sen tekemään...

hunajavohveli [30.01.2008 21:59:40]

#

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ä.

tgunner [31.01.2008 20:53:53]

#

Hih, nostalgiaa. Siinä on mallia moottorista. :)

vehkis91 [01.02.2008 19:37:01]

#

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;
}

vehkis91 [02.02.2008 12:41:04]

#

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".

Gaxx [02.02.2008 23:04:12]

#

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 :)

vehkis91 [03.02.2008 13:44:26]

#

No en ole vectoreita pahemin käyttäny, mutta kerta se on ensimmäinenkin... ;)

Kiitos neuvoista!!!

Edit:
Saisiko sitä vectori ohjetta jostain suomeksi?

WinC [03.02.2008 14:00:45]

#

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.pdf

vehkis91 [03.02.2008 16:53:40]

#

Miksi dev-c++ 4.9.9.2 ei tunnista string käskyä????!!!

Gaxx [03.02.2008 16:58:05]

#

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.

vehkis91 [03.02.2008 17:01:17]

#

mullon

#include <string>
using namespace std;

Eikä toimi...

Gaxx [03.02.2008 17:02:32]

#

No millaisen virheilmoituksen se antaa? Anna koko litanja.

vehkis91 [03.02.2008 17:03:53]

#

Edit:
Hups

Unohdin ton namespacen...


EDIT:::
Miten luen sen koko tiedoston muistiin ja sen jälkeen vasta katson tietyn osan siitä?

kayttaja-3842 [03.02.2008 17:37:54]

#

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!

vehkis91 [03.02.2008 19:33:04]

#

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)

Gaxx [03.02.2008 20:28:48]

#

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.

vehkis91 [04.02.2008 10:40:10]

#

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????

Gaxx [04.02.2008 11:08:50]

#

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();

os [04.02.2008 15:19:20]

#

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.

vehkis91 [04.02.2008 18:34:45]

#

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...

Gaxx [04.02.2008 19:08:43]

#

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.

vehkis91 [04.02.2008 19:30:29]

#

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?

Gaxx [04.02.2008 19:49:25]

#

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.

vehkis91 [04.02.2008 19:55:44]

#

okey


Sivun alkuun

Vastaus

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

Tietoa sivustosta