Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Pikkupelin kentät

Sivun loppuun

Jyri [06.12.2004 21:39:47]

#

Eli tavoitteenani (siis haaveenani (: ) on tehdä pikkupeli C++:lla.
Kysymys koskee kenttien luontia. Eli miten minun kannattaisi tehdä mapit? Mapit tulisi olemaan tätä tyyliä:

+-----+
|___  |
|     |
+-----+

Mutta miten ne kannattaisi luoda, sillä ei välttämättä ole kovin hyvä idea näpytellä kaikkia kenttiä ihan suoraan siihen koodin. Ja kannattaako mapit lukea taulukkoon? Ja miten se tarkalleen toimisi?

rndprogy [06.12.2004 21:49:01]

#

Tuollaiset merkkigrafiikkaiset (vai meinaatko tileillä tehdä) kartat kannattaa tallentaa tiedostoon ja lukea sitten sieltä. Se on luullakseni ehkä paras vaihtoehto.

Metabolix [06.12.2004 22:10:54]

#

Taso kannattaa ehdottomasti ladata tiedostosta, niin myöhempi muokkaaminen on helpompaa. Käytä vaikkapa char-taulukkoa, tai, jos jokaiselta palaselta tarvitaan enemmän ominaisuuksia, voit luoda oman structin taulukossa käytettäväksi. Tiedostosta voi lukea fread-funktiolla, jolloin datan saa binäärimuodossa. Jos käytät structeja, ei ole kovinkaan vaikeaa tehdä pientä ohjelmaa, joka tekee sattumanvaraisen kartan tiedostoon. Helppo rakenne on vaikkapa se, että ensin luetaan tietuetta "struct TOtsikko", joka sisältää tiedon tason leveydestä, korkeudesta ja muista merkittävistä tiedoista, ja sen jälkeen luetaan oikea määrä (Leveys * Korkeus) struct TRuutu -tietuetta taulukkoon. Eräänlainen esimerkki:

#include <stdio.h>

// TPala voi olla ihan hyvin vain char, jos tasolta ei vaadita enempää.
#define TPala char

// Otsikon on hyvä sisältää kaikki perustiedot tasosta.
struct TOtsikko
{
  int Leveys, Korkeus;
};

TPala *Tasotaulu;
TOtsikko Otsikko;

// Määritellään makro, jolla saadaan tasosta tietty pala:
#define Taso(X, Y) Tasotaulu[X + Y * Otsikko.Leveys]

void LataaTaso(char *Tiedostonimi)
{
  // Avataan tiedosto
  FILE *hFile = fopen(Tiedostonimi, "r");

  // Luetaan Otsikkoon yksi TOtsikon kokoinen pala hFile-tiedostosta.
  fread(&Otsikko, sizeof(TOtsikko), 1, hFile);

  // Varataan muistia.
  Tasotaulu = new TPala[Otsikko.Leveys * Otsikko.Korkeus];

  // Luetaan Tasotauluun kaikki tason palat
  fread(Tasotaulu, sizeof(TPala), Otsikko.Leveys * Otsikko.Korkeus, hFile);
}

int main()
{
  LataaTaso("Taso1.lev");
  printf("Taso ladattu!");

  for (Y = 0; Y < Otsikko.Korkeus; Y++)
  {
    for (X = 0; X < Otsikko.Leveys; X++)
    {
      printf("%c", Taso(X, Y)); // Tulostetaan kohdan (X, Y) merkki
    }
    printf("\n"); // Rivin vaihto
  }

  // Muistetaan aina myös tuhota taso, jotta muisti vapautuu.
  delete [] Tasotaulu;

  return 0;
}

Tason saa siis luotua niin, että täyttää TOtsikko-tietueen, kirjoittaa sen tiedostoon (esim. fwrite-funktiolla) ja kirjoittaa sen jälkeen (Leveys * Korkeus) TPala-oliota, joka siis on tuossa tapauksessa sama kuin char.

Jyri [07.12.2004 10:09:34]

#

Kiitti! Toi oli tosi perusteellinen vastaus.

Jyri [07.12.2004 13:03:05]

#

Niin, nyt tulikin ongelma, että miten saisin luettua näppäimistön painalluksia? Siis tietty nuolinäppäimiä. Eli millä funktiolla se onnistuu?

Heikki [07.12.2004 13:05:10]

#

Tarvitset jonkin kirjaston käyttöösi. Esimerkiksi SDL:llä tämä onnistuu. Putkasta löytyy oppaat.

ZcMander [07.12.2004 13:34:09]

#

Ncurses(unix*), tai sitten PDcurses(windows), niillä onnistuu näppäinten luku getch(); komennolla

esim.

#include <ncurses.h>

int main()
{
    int a = 0;

    a = getch();

    switch(a) {
       case KEY_A:
           printw("Painettiin A:ta");
    }
    return 0;
}

PS: Sisältää virheitä, koska kirjotin suoralta kädeltä, mutta asia pitäis tulla selväksi, eli getch() ei palauta näppäimen kirjainta vaan vissiin ASCII koodin, joka kuitenkin on #define:llä ohjattu tyyliin: KEY_(kirjain tähän)

EDIT: ainiin toi sun esimerkki ei toimi koska tuosta puuttuu int X ja int y sekä mulla se sanoo (siis vaikka taso o olemassa): what(): St9bad_alloc
Keskeytetty

Metabolix [07.12.2004 17:28:37]

#

No onko niin suuri juttu lisätä tuonne "int X, Y;"? Huomioi, että kirjoitin tuon suoraan tähän pieneen viestilaatikkoon. Muilta osin tuo toimisi, jos sinulla olisi tuon kaavan mukainen tasotiedosto (Taso1.lev), ja sitä sinulla ei tietenkään ole. Totta kai tuosta tulee "bad alloc", kun (Width * Height) on ties kuinka suuri luku, kun siihen ei ole tiedostosta saatu järkevää arvoa. Järjen käyttö sallittu.

Jyri [09.12.2004 14:11:50]

#

ÄÄH! Mä en saa ees tota ZcManderin esimerkki koodia toimimaan :( SHIT!
En oo vieläkään alkuu pidemmällä :(. Eli taidan aloittaa alusta:
Eli, jos nyt aluksi haluaisin tehdä (tulevaan) peliini ukkelin liikutuksen (aloin säätämään vanhaa ja se meni epäkuntoon (: ), niin miten se onnistuisi? Eli pitäisikö tämän toimia:

#include <iostream>
#include <conio.h>

using namespace std;

int main()
{
   gotoxy(4, 5);
   cout << "*";
   getch();
}

Eli pitäisikö tuon koodin laittaa tähti(*) näytölle kohtaan X4 ja Y5?

ZcMander [09.12.2004 15:50:17]

#

Conio.h:sta en mene takuuseen, se nimittäin taitaa vain löytyä Borlandin kääntäjästä, lisäksi sanoi, että PDcurses tai Ncurses (ainakin Ncurses) löytyy getch() komento. Taitaa (En allekirjota) olla conio.h:ssa, gotxy komento on kyllä conio.h:ssa

Nurses(tai PDcurses, mutta en ole siihen tutustunut):sin piirto funktio tulee muistaakseni näin:

//mvprintw(rivi,sarake,teksti);
//esim.
mvprint(4,5,"*");
//Tuo piirtää haluamaasi kohtaan tähden

EDIT:Ncurses:lla haetaan maksimi koot käyttämällä komentoa getmaxxy(int w,int h); Lisätietoa löytyy Ncurses ohjelmointi oppaassa (engl.) http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/index.html

EDIT2:Itsekkin tein merkkipohjasta peliä ja onnistuinki siinä ja aloin lisää kehittämään, mutta sortui huonosti koodattuun engineen (ei luokkia :O), eli nytten mulla on itellä ollut aika kauan merkkipohjanen peli kehitteilla (Eikä pelin idea tullut hov:sta)

Aruviel [09.12.2004 16:01:24]

#

Miksi sitten edes mainitsit HoV:n? ;). Ei vaiskaa, toivottavasti saadaan kuulla viel* pelist*si. Ja se on mvprintw, ei mvprint. Mvprintw kirjoittaa haluttua teksti* xy kohtaan stdscreeni*.

Jyri [09.12.2004 16:02:08]

#

Mutta mikä headeri tuolle mvprint():ille tarvitaan?

ZcMander [09.12.2004 17:28:39]

#

Aruviel, kirjoititko tahallas tähtinä?

Mutta itse asiaan: Joo, kyllähän multa unohtui tuo w tuolta perästä, kuteskin kommenteissa se on oikein, lisäksi minun tietääkseni tekstitilassa ei ole x ja y:tä (tosin itsekkin niitä käyttelen ;) vaan rivi ja sarake. Tuohan tarttee headereiksi:

Windows:
#include <curses.h>

Linux:
#include <ncurses>

Ja molemminlla pitää linkitää kirjasto ncurses/PDcurses, GCC:llä onnistuu (ncurses): gcc lahde.cc -o peli -lcurses

Juice [09.12.2004 19:01:35]

#

ZcMander kirjoitti:

Conio.h:sta en mene takuuseen, se nimittäin taitaa vain löytyä Borlandin kääntäjästä

Löytyy myös Dev-C++:sta.

Jyri [10.12.2004 15:49:02]

#

Mul ei toi curses.h:n mvprintw/mvprint() eikä conio.h:n gotoxy() toimi... Mikä tässä nyt neuvoksi? Aika outoa ettei ess toi curses juttu toimi...

Metabolix [10.12.2004 17:43:45]

#

Mikä siis on ongelma? Eikö tarvittavaa otsikkoa löydy, vai yritätkö väittää, etteivät funktiot toimi? PDCurses-kirjoston saa osoitteesta http://sourceforge.net/project/showfiles.php?group_id=30480

ZcMander [10.12.2004 19:39:04]

#

Ei tietenkään ole, kun se ei ole standarti kirjasto.

Se pitää hakea, kuten kaikki muutkin kirjastot. Dev-c++ Updater ohjelmalla saatta löytyä, mutta jos ei löydy niin sitten se pitää itse säätää. Siinä en valitettavasti osaa auttaa.

Itse asensin Linuxsin itse asentuvista RPM paketeista ;)

Jyri [11.12.2004 09:44:56]

#

En nyt varsinaisesti väitä, ettei PDcurses toimi, vaan en itse saa sitä toimimaan.
Eli pitäisikö tämän koodin asetella tähti(*) näytölle kohtaan X5 Y4:

#include <iostream>
#include <curses.h>
using namespace std;
int main()
{
   mvprint(5, 4, "*");
   return 0;
}

Ja tuon koodin kääntää näin:
Menee komentoriville ja Dev-Cpp/bin kansioon, sitten antaa komennon:
gcc testi.cpp -o testi.exe -Icurses

Eli pitäisikö tuon toimia?

Aruviel [11.12.2004 09:54:15]

#

Käännät C-kääntäjällä (gcc), vaikka iostreamia ei löydy C:stä. Käännä siis g++:lla. Ja minähän sanoin, ettei - ainakaan ncursesissa - ole sellaista funktiota kuin mvprint(), se on mvprintw(). Jos haluat yksittäisiä merkkejä tunkea ruutuun, käytä mvaddch(int y, int x, char ch); -funktiota. Huomaa, että curses ohjelmissa tulee ensiksi ilmoittaa sijainti y-akselilla ja sen jälkeen x-akselilla.

// Funktiot tunkevat (ensimmäisellä vain merkkejä, toisella merkkijonoja) merkin * kohtaan X=4, Y=5. Huomaa myös, että X ja Y alkavat nollasta, joten jos haluat merkin vasempaan yläkulmaan, sinun tulee käyttää X=0, Y=0.

mvaddch(5,4,'*');
mvprintw(5,4,"*");

http://en.tldp.org/HOWTO/NCURSES-Programming-HOWTO/printw.html

Jyri [11.12.2004 11:50:53]

#

Ei toimi... Siis vaikka hain PDcursesin, tein asettelemis koodin niinkuin neuvottiin ja käänsin tiedoston niinkuin neuvottiin... Mikähän tässä nyt mättää?

Aruviel [11.12.2004 12:21:42]

#

Onko se asennettu? Lisäksi helpottaisi aivan mielettömästi, jos virheet olisivat täällä näkyvillä.

Jyri [11.12.2004 14:05:00]

#

Joo, kyllä on asennettu :)
Se ilmottaa:
undefined referece to 'mvprintw'

Mitäkähän toi nyt sitte tarkottaakaa... (:

ZcMander [11.12.2004 14:51:02]

#

Hmm, käytä g++ kääntäjää niin onnistuu, sama ongelma oli minulla. Noh, riippuu tietenkin mitä ohjelmaa käytät, DEV-c++ ohjelmassa lienee pitää laittaa c++ ohjelmaksi ja lisätä libraryt (siis ei pelkästään otsikko tiedostot).

Niin ja tuohan virhe ilmo tulee linkitysvaiheessa, ei käänösvaiheessa, joten libraryt on aika varma syy jos käytät Dev-c++. Ne saa laittamalla asetuksista (yllätys). Lisäksi kannaattee varmuuden vuoksi laittaa koodi tänne. (Joka ei kai ole kovin pitkä?)

Jyri [11.12.2004 15:00:53]

#

Koodi on tossa vähän ylempänä, paitsi että nykyään osaan kirjoittaa mvprintwin oikein :P

ZcMander [11.12.2004 20:23:55]

#

Tarkoitin koko koodia, toimiiko tämä koodipätkä:

#include <curses.h>

int main()
{
	initscr();			/* Start curses mode 		  */
	printw("Hello World !!!");	/* Print Hello World		  */
	refresh();			/* Print it on to the real screen */
	getch();			/* Wait for user input */
	endwin();			/* End curses mode		  */

	return 0;
}

Jyri [11.12.2004 20:28:46]

#

Toi ei toimi. Väitää virhettä joka rivistä :D
Ja varsinaista muuta koodia ei ole, koska olen vasta ihan projektin alussa.

Juice [11.12.2004 21:14:21]

#

Tein ukon liikutuksen, kääntyy ainakin Dev-C++:ssalla. Muista lisätä projektiisi conio.c.

#include <conio.h>
#include <stdio.h>
using namespace std;

int gox, goy;
int main(int argc, char *argv[])
{
   for(;;){
           int a = 0;
           a = getch();
           //Tyhjennetään näyttö
           clrscr();
           switch(a) {
           case 75:
                gox--;
                break;
           case 77:
                gox++;
                break;
           case 72:
                goy--;
                break;
           case 80:
                goy++;
                break;
           }
           gotoxy(gox,goy);
           printf("*");
   }


}

Jyri [11.12.2004 21:59:18]

#

Siis miten toi conio.c pitää lisätä projektiin?

Blaze [11.12.2004 22:07:41]

#

#include:lla kenties?
(Mikä tuon #includen oikea nimitys muuten on? Komento? Direktiivi? Esikääntäjän ohje?)

tn [12.12.2004 00:10:47]

#

Project-valikosta -> Add to project (Olettaen, että onjelmasi yleensä on projekti)

Jos käyttää pelkkää yhtä lähdekooditiedostoa ilman projektia, niin on helpompaa sisällyttää se tuon conio.h :n sijasta.

Jyri [12.12.2004 12:06:14]

#

Hmm... Mulla toi gotoxy koodi ilmottaa:
'gotoxy' undeclared (fist use this function)
eli ei toimi...

Jyri [12.12.2004 12:30:50]

#

Nyt sain ton curses.h:n mvprintwnin menemään kääntäjästä läpi; oli kirjottanu -Icurses vaikka piti kirjottaa -lcurses :@. Ainut ongelma on vielä se, että se mvprintw ei asettele sitä merkkiä, vaan piirtää tyhjää :O Mikä siinä nyt voisi olla vikana?

Koipio-ohjelma [12.12.2004 12:50:52]

#

#include on ainakin minun mielestäni esikääntäjän ohje...
Mutta taas kerran muistutan että se on minun mielestä niin...

Jyri [12.12.2004 15:24:33]

#

Nyt sain ton toimimaan tolla curses.h:lla :D JEAH!!
Nyt vaan tuli eteen sellanen ongelma, että luen näppäimet conio.h:n getch() oliolla, mutta mitenkäs se suu pannaan, kun curses.h:ssakin on getch()? eli nyt ne menee sekasin! Miten ton vois korjata. Pitääkö conio.h:ta muokata tai jotain?

Metabolix [12.12.2004 15:26:02]

#

Mitä jos rupeaisit käyttämään pelkkää PDCursesia ja luopuisit coniosta kokonaan?

ZcMander [12.12.2004 15:55:19]

#

Jyri, sen takia ei tullut mitään koska perään pitää laittaa refresh(); komento joka päivittää näytön. Ja kuten ylläkin on sanottu, käytä pelkästään PDcurses kirjastoa, siitä löytyy getch(); Emt miksi jotku on ees sekottanut conio.h ja PDcurses:sin keskenään?

Juice [12.12.2004 18:22:22]

#

ZcMander kirjoitti:

Emt miksi jotku on ees sekottanut conio.h ja PDcurses:sin keskenään?

Koska molemmissa on tämä gotoxy/mvprintw.

Käytä nyt vaan sitä PDCursesia, se on monipuolisempi kuin conio :P

Jyri [13.12.2004 08:07:56]

#

Mutta ku se pdcursesin getch() ei kai toimi ihan samallatavalla kuin conio.h:n getch(), tai siis ainakaan samaa koodia se ei pysty käyttämään. Pitäskö sen siis toimia näin:

int a = 0;
a = getch();
if(a == 75) x -= 1;

???

sqwiik [13.12.2004 10:42:03]

#

PDCurses:n getch() ei palauta samoja arvoja kuin conion vastaava (näin muistelisin). PDCurses:n mukana tulevassa .H-tiedostossa on määriteltynä vakiot tuolle getch():lle (KEY_A, KEY_LEFT tms). Koeta katsoa jos löytyy/toimii, tai sitten vai testaat erikseen mitä se palauttaa.

Jyri [13.12.2004 16:14:17]

#

Hmm.. ainakaan se ohjelma jolla yritän näppäimistöä lukea ei toimi... Eli se ei tee sitä mitä sen pitäisi tehdä kun painetaan alas, vaan se sammuu.

ZcMander [13.12.2004 16:49:19]

#

Kertoisit koodin.

Simple koodi:

#include <iostream>
#include <curses.h>

using manespace std;

int main() {

    int nappain = 0;

    initsrc();

    nappain = getch();

    switch(nappain) {
           case KEY_LEFT:
                cout << "Painoin vasemmalle" << endl;
    }

    endwin();
}

Jyri [13.12.2004 17:21:50]

#

Hmm.. toi ohjelma ei toimi mulla, se vaan vilahtaa eikö oota mitään napin painallusta.

Draiz [13.12.2004 17:24:56]

#

Jyri kirjoitti:

Hmm.. toi ohjelma ei toimi mulla, se vaan vilahtaa eikö oota mitään napin painallusta.

http://pp.kpnet.fi/blaze/codefaq/#justflashes

Jyri [13.12.2004 18:53:16]

#

Joo, oisit voinu lukea vähän noita edellisiä viestejä, nyt kysymys ei ollut siitä, vaan siitä ettei tulo curses.h:n getch(); toiminut oikein.

Juice [13.12.2004 18:56:39]

#

Laita for(;;)-looppiin (tai vaihtoehtoisesti while(1)).

EDIT: Vähän muuteltu PDCurses-esimerkistä. Sovella.

/*
	Based on: http://www.linux.cz/noviny/1998-1112/clanek11.html
*/
#include <curses.h>
#include <ctype.h>


int main () {
	int	c;
	initscr ();
	keypad (stdscr, TRUE);

    while ( (c=getch()) != KEY_F(10)) {
		erase();
        //Tunnista vasen
        if (c == KEY_LEFT){
			mvprintw (10, 20, "VASEN!!!", s);
		}
	}

	erase ();
	refresh ();
	endwin ();
	exit (0);
}

EDIT2: Olin kiltillä päällä ja tein paremman.

Aruviel [13.12.2004 19:04:32]

#

(Viitaten getch(); ongelmaan)

Miten niin ei toimi oikein? Kerrot aina yhtä tarkasti ongelmasta. Arvuuttelu ei ole kivaa. Luepa niitä oppaita, miten asia tehdään. Alkuunsa sanon, että funktiokutsut noecho(); ja raw(); liittyvät jotenkin asiaan.

http://en.tldp.org/HOWTO/NCURSES-Programming-HOWTO/init.html

Jyri [14.12.2004 10:10:18]

#

Kiitti! Nyt toimii!


Sivun alkuun

Vastaus

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

Tietoa sivustosta