Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: SDL ja Näppäimet

Sivun loppuun

tkok [14.08.2008 22:30:06]

#

Tekemäni Editori ei jostain syystä lue näppäimiä.

Escapesta ei mene pois ohjelmasta eikä numeronäppäimillä ole vaikutusta.

listaan tähän koko koodin koska ei ole hajuakaan missä päin se vika luuraa.

/* Tomillan NS kenttäeditori

	EDIT: ei liity: (versio	->	0.0.5
				0.1.0 =>toimivuutta
				0.2.0 =>tiedoston hallintaa
				0.3.0 =>Kuvien osoitteet ja määrien hallinta paremmaksi)

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "SDL.h"
//Tarpeelliset kirjastot haettu

int taulu[12][16]={	{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
					{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
					};//Alustetaaan taulukko piirto kuntoon
int numero = 0;		// mitä objektia käytetään
int H_x;			// hiiren x ja y
int H_y;
int H_napit;		// hiiren nappi
int pois;			// poistutaanko ohjelmasta


void Hiiren_sijainti(void);				//Funktio hakee hiiren sijainnin
void Nappain_paino(void);				//Funktio tekee näppäinpainallusten tarvitsemat toiminnot
void Piirto(void);						//Funktio huolehtii
void Piirra(int objekti, int X, int Y); //Funktio huolehtii yksittäisen kuvan piirtämiseltä
SDL_Surface *screen;					// näytölle piirto pinta
SDL_Surface *kuva;						// Kuvalle piirto pinta


int main(int argc, char *argv[])		//Main funktio->Näytön asetukset, pää looppi, muistin vapautus
{
	Uint32 initflags = SDL_INIT_VIDEO; // näytön asettamisen tarkistusta varten

	Uint8  video_bpp = 32;												// Värisyvyys = 32 bittinen
	Uint32 videoflags = SDL_SWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF; // lipukkeet: käytä_normaaliamuistia | Kokonäyttötila | kaksoispuskurointi




	if ( SDL_Init(initflags) < 0 ) {	//tapahtuuko virhe
		fprintf(stderr, "Couldn't initialize SDL: %s\n",
			SDL_GetError());
		exit(1);
	}

																//Asetetaan näytön asetukset
	screen=SDL_SetVideoMode(1024,768, video_bpp, videoflags);	//Tekee yhteensä 16x12 ruutuisen näytön (1 ruutu 64x64 px), värisyvyys, lataa lipukkeet
        if (screen == NULL) {									//jos näyttö jää tyhjäksi tapahtui virhe ja keskeytetään ohjelma
		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
                        video_bpp, SDL_GetError());
		SDL_Quit();
		exit(2);
	}



	pois = 0;			//asetetaan poistujamuuttuja nollaksi
	while ( !pois ) {	//jatketaan kunnes halutaan poistua

Hiiren_sijainti();		//Haetaan hiiren sijainti
Nappain_paino();		//tee näppäinten edellyttämät toiminnot
Piirto();				//piirrä
SDL_Delay(500);		//odota hetki ja jatketaan






	}
	SDL_FreeSurface(kuva);					//puhditetaan pinnat ja SDL kirjasto
    SDL_FreeSurface(screen);
	SDL_Quit();
	return(0);
}



void Hiiren_sijainti(void){
	H_napit=SDL_GetMouseState(&H_x, &H_y);	//lukee H_napit-muuttujaan painallettu nappi ja hiiren sijainti H_x ja H_y muuttujiin

}


void Nappain_paino(void){
	Uint8* nappi;
	SDL_Event tapahtuma;					// ennen näppäinten lukemista tulee lukea tapahtumat?
	SDL_PollEvent(&tapahtuma);

	if(H_napit == SDL_BUTTON(1)){taulu[(H_x/64)][(H_y/64)]=numero;} //jos hiirellä on painettu vasenta h näppäintä laitetaan taulukkoon hiiren kohtaan objektin numero

	nappi = SDL_GetKeyState(NULL);
			if ( nappi[SDLK_1] ) { numero = 1; }
			if ( nappi[SDLK_1] ) { numero = 1; }
			if ( nappi[SDLK_2] ) { numero = 2; }
			if ( nappi[SDLK_3] ) { numero = 3; }
			if ( nappi[SDLK_4] ) { numero = 4; }
			if ( nappi[SDLK_5] ) { numero = 5; }
			if ( nappi[SDLK_6] ) { numero = 6; }
			if ( nappi[SDLK_7] ) { numero = 7; }
			if ( nappi[SDLK_8] ) { numero = 8; }
			if ( nappi[SDLK_9] ) { numero = 9; }
			if ( nappi[SDLK_0] ) { numero = 0; }
			if ( nappi[SDLK_ESCAPE] ) { pois = 1; }

}


void Piirto(void){							//taulukon piirto
	for(int i=0; i<=11; i++)
	{
		for(int j=0; j<=15; j++)
		{
			Piirra(taulu[i][j], j*64, i*64);//käydään taulu läpi
		}
	}
	Piirra(numero, (H_x/64)*64, (H_y/64)*64); //jotta H_x olisi 64 jaollinen luku,
	SDL_Flip(screen);
}







void Piirra(int objekti, int X, int Y){	//kuvien piirto


if(objekti == 0){kuva=SDL_LoadBMP("/NS/Kuvat/0.bmp"); }
if(objekti == 1){kuva=SDL_LoadBMP("/NS/Kuvat/1.bmp"); }
if(objekti == 2){kuva=SDL_LoadBMP("/NS/Kuvat/2.bmp"); }
if(objekti == 3){kuva=SDL_LoadBMP("/NS/Kuvat/3.bmp"); }
if(objekti == 4){kuva=SDL_LoadBMP("/NS/Kuvat/4.bmp"); }
if(objekti == 5){kuva=SDL_LoadBMP("/NS/Kuvat/5.bmp"); }
if(objekti == 6){kuva=SDL_LoadBMP("/NS/Kuvat/6.bmp"); }
if(objekti == 7){kuva=SDL_LoadBMP("/NS/Kuvat/7.bmp"); }
if(objekti == 8){kuva=SDL_LoadBMP("/NS/Kuvat/8.bmp"); }
if(objekti == 9){kuva=SDL_LoadBMP("/NS/Kuvat/9.bmp"); }

  SDL_Rect alue; // mille alueellä näyttöä kuva piirretään
  alue.x = X; // koordinaatit
  alue.y = Y;
  SDL_BlitSurface(kuva, NULL, screen, &alue);





}

vehkis91 [14.08.2008 22:54:20]

#

[Offtopic]
Miksi tuolla ylhäällä lukee "0.2.0 =>tiedoston hallintaa ", minä en ainakaan näe yhtään tiedostonhallinta-funktioita tuolla koodissa... (Taidan olla sokea)...

Elleis se sitten tarkoita noita kuvien lataamista...
[/Offtopic]

Minulla tulee tuollaista virhettä ku yrittää kääntää...

main.c:126: error: ‘for’ loop initial declaration used outside C99 mode
main.c:128: error: ‘for’ loop initial declaration used outside C99 mode

Yritän selvittää mistä johtuu..-


EDIT: käänsin c++ kääntäjällä ja kääntyi nätisti...
Minulla ainakin lähtee esciä painamalla pois ohjelmasta...

tkok [14.08.2008 22:59:46]

#

Öh, anteeksi, jäi tuo versionkehityssuunnitelman runko sinne alkuun :(

tgunner [14.08.2008 23:04:39]

#

Ensinnäkin onnittelut päänsärkyisestä koodin ulkonäöstä, mutta älä huoli, se paranee, kun ohjelmoi enemmän. :)

Tapahtumia ei tarvitse pumpata ennen näppäinten lukemista.

Alustat taulu-muuttujan muodolla taulu[y][x], mutta koodirivillä

if(H_napit == SDL_BUTTON(1)){taulu[(H_x/64)][(H_y/64)]=numero;}

käsittelet sitä muodossa taulu[x][y]. Tästä voi seurata mitä kummallisimpia seurauksia!

Sanoit: "Escapesta ei mene pois ohjelmasta eikä numeronäppäimillä ole vaikutusta", mutta en yhdy tähän väittämään. Eski toimi hienosti, ja näppäimistöllä sain valittua kuvat, jotka itse piirsin. Ongelmasi saattaa johtua väärin muotoillusta tiedostopolustasi. Olet kirjoittanut SDL_LoadBMP("/NS/Kuvat/9.bmp"). Ota ensimmäinen vinoviiva polusta pois.

Lisäksi kutkuttaisi kertoa pari kikkaa, joilla voisit selventää ja parantaa koodiasi, mutta eivätköhän ne muotoudu sinulle automaattisesti, jos pysyttelet ohjelmoinnin parissa.

edit. niin ja tuo muistivuoto! Lataat kuvat uudestaan ja uudestaan jokaisella piirtokerralla. Niiden vapauttaminen ohjelman lopussa ei jeesaa kovin paljoa. :)

Metabolix [14.08.2008 23:07:40]

#

Koodi on ilmeisesti tätä kuuluisaa C/C++:aa eli melkein C:tä muttei aivan. C99:nä tuo mennee läpi (en jaksa kokeilla), GCC:n lippu -std=c99, jos vehkis91 haluaa kokeilla. Virhehän on aivan selvä, jos C:n perusteet ovat hallussa. C++ on sen verran vapaampaa, ettei tuollaista virhettä tule.

Suosittelen tapahtumien lukemista semanttisesti, eli jos et käytä niitä mihinkään, käske SDL_PumpEvents-funktiolla SDL:n hoitaa kaikki jonossa olevat, ja jos taas käytät, niin lue kaikki jonosta aina kerralla (while (SDL_PollEvent(...)) {hoida...}) äläkä vain yhtä ohjelman joka kierroksella.

Ohjelmasi vuotaa muistia aivan mielettömästi, lataat joka piirtokerralla kuvat uudestaan etkä vapauta kuin lopuksi sen yhden, johon kuva-osoitin sillä hetkellä osoittaa. 16x12 tilen tasolla tämä tarkoittaa, että joka piirtokerralla lataat ja hukkaat 192 kuvaa jo pelkän taustan takia. Ei ihme, jos mitään ei näy. Oletko edes varma, että ohjelma pääsee SDL_Flip-funktioon asti? Noin epäoptimaalisella toteutuksella jo piirto voi kestää pitkään. Lisää piirtofunktioon (sekä Piirto että Piirrä) debug-printtausta ja aseta pääohjelman silmukassa pois-muuttuja heti ykköseksi, jotta silmukka suoritetaan vain kerran. Debug-tulosteessa voit myös tarkistaa, että kuvaosoitin ei ole NULL. Ihmettele sitten lisää, kun tiedät, mitä ohjelma edes yrittää piirtää. Myös kuvapolkusi näyttävät varsin epäilyttävältä, et kai sentään juurihakemiston alla kuviasi pidä? Varmaan pitäisi ensimmäinen "/" poistaa jokaisesta. Tarkista aina dataa ladatessasi, että lataus onnistuu.

Tee fiksusti: lataa kuvat ohjelman alussa taulukkoon (SDL_Surface *kuvat[10]) ja vapauta kaikki kymmenen lopuksi. Ei tarvitse välillä latailla, ei vuoda muistia, ja koodiakin säästyy, kun voit kirjoittaa vain "kuvat[numero]" noiden kymmenen if-lauseen sijaan.

vehkis91 [14.08.2008 23:09:02]

#

Minäkin piirsin itse kuvat, ja ne kuvat piirtyivät eri kohtiin kuin missä hiiri olim eli sulla on koordinaattien kanssa jokin ongelma...

Ja annan yhden vinkin ainakin käytä struct tai class.

ja sitten #include <string.h> -> #include <string>

ja sitten niiden headereiden jälkeen using sdl::string;

EDIT: Metabolix: Minulla ainakin piirtää ne kuvat, mutta väärään kohtaan, koska tuossa yhdessä vaiheessa nuo kordinaatit vaihtavat paikkaa.

Metabolix [14.08.2008 23:16:03]

#

vehkis91 kirjoitti:

ja sitten #include <string.h> -> #include <string>

Ei todellakaan. Nuo ovat kaksi täysin eri otsikkoa, voit tutustua asiaan vaikkapa Googlen avulla. Ensimmäinen sisältää C:n tekstin- ja muistinkäsittelyfunktioita.

vehkis91 kirjoitti:

EDIT: Metabolix: Minulla ainakin piirtää ne kuvat, mutta väärään kohtaan, koska tuossa yhdessä vaiheessa nuo kordinaatit vaihtavat paikkaa.

Missä kohti? Pikaisella silmäyksellä kaikki menee aivan loogisesti. Jos tarkoitat i:tä ja j:tä Piirto-funktiossa, katso toki vielä tarkemmin ja käy vilkaisemassa, miten päin se taulukko olikaan (eli y, x eikä x, y).

vehkis91 [14.08.2008 23:21:13]

#

EN tarkoita, kun niitä, että aluksi oli y, x ja llopussa taas x,y, kun muutin niin alkoi pelaan ihan kunnolla.

Jaa sori tuosta stringistä, en c:tä ole pahemmin käyttänyt, joten...

Edit: siis tuo mitä tgunner kirjoitti.

tkok [14.08.2008 23:23:06]

#

Kiitos vastauksesta

Huomasit selvästi, että olen aloittelija ohjelmointipuolella. Pyrin jatkossa keskittymään tarkemmin koodin ulkonäköön, aloittelijamokailujen vähentämiseen ja koodin optimointiin.

For silmukat eivät aiheuttaneet Apple(PowerPC)/Xcode (tästä johtuen tulee olla /-merkki ennen kuvanpolkua) kääntäjällä mitään error herjaa. Näppäimillä ei ollut vaikutusta, nyt kuitenkin kun vaihdoin x ja y oikein, niin palikka kyllä seuraa hiiren liikkeitä mutta erittäin tahmeasti, aluksi nopeammin mutta noin sekunnin ajon jälkeen muuttuu tahmeeksi: hiiri liikkuu ja kuva tulee noin sekunnin viiveellä perässä.

Näppäimissä ei siis ollut mitään vikaa, ne toimivat kun jaksaa vaan pitää pohjassa n. sekunnin.

Onko koneesi uudehkompi kuin tämä n 2,5vuotta vanha ibook G4 apple?

Ehkä ajatus liikkuu huomenna nopeammin ja jatkan sitten debuggausta.

Laitinen [14.08.2008 23:24:55]

#

vehkis91 kirjoitti:

ja sitten #include <string.h> -> #include <string>

ja sitten niiden headereiden jälkeen using sdl::string;

Tarkoitat varmaankin std::string;. Muutenkin tuo vaihdos ei oikein tee mitä halusit, kuten Metabolix jo huomauttikin.

vehkis91 [14.08.2008 23:26:13]

#

No en yhtään ihmettele, jos alkaa hidasteleen ku lataat joka kerta nuo kuvat uudelleen...

Metabolix [14.08.2008 23:29:02]

#

Jaa niin, [koordinaatit väärin] käsittelyssä eikä piirrossa. Minusta se silti piirtää aivan oikein mutta klikkaus käsitellään väärin. Tässä ohjelmassa ero ei ole niin konkreettinen, mutta esimerkiksi pienessä pelissä on jo hyvin olennaista, piirretäänkö ukkeli aivan väärään paikkaan vai liikkuuko se oikeastikin jostain syystä sinne. (Ensimmäinen on joskus paljon ikävämpi ongelma, koska se voi olla vaikeampi havaita, vaikka korjaaminen ehkä olisikin helpompaa.)

Edit. Itse aiheeseen vielä: Miksi XCode (tai Mac) aiheuttaa tuollaisen vaatimuksen tiedostopolkuun? Sen kerran, kun Macia käytin, käyttäjän kotihakemisto oli /Users-hakemiston alla, ja pitäisin järkevänä oman kotihakemiston käyttämistä.

Ohjelman hidastuminen luultavasti johtuu juuri mainituista muistivuodoista, ja muutenkin hitautta aiheuttaa tuo SDL_Delay, jolla käsket ohjelman odottaa aina puoli sekuntia, ja kuvien jatkuva latailu.

vehkis91 [14.08.2008 23:48:05]

#

Juu sain toimimaan tuon täysin reaaliaikaisesti, kun tein tarvittavat muutokset.

Tässä pitäis olla kaikki tarvittavat muutokset.
Nuo muut voivat sanoa, jos teen jotain väärin...

PS. sain kääntymään c-kääntäjälläkin... :P


lataaKuvat():

void lataaKuva() //Laitat sitten sen protyypin ennen mainia.
{                //ja kutsut mainista tätä ennen sitä päälooppia.
 kuva[0]=SDL_LoadBMP("0.bmp");
 kuva[1]=SDL_LoadBMP("1.bmp");
 kuva[2]=SDL_LoadBMP("2.bmp");
 kuva[3]=SDL_LoadBMP("3.bmp");
 kuva[4]=SDL_LoadBMP("4.bmp");
 kuva[5]=SDL_LoadBMP("5.bmp");
 kuva[6]=SDL_LoadBMP("6.bmp");
 kuva[7]=SDL_LoadBMP("7.bmp");
 kuva[8]=SDL_LoadBMP("8.bmp");
 kuva[9]=SDL_LoadBMP("9.bmp");
}

globaalit:
SDL_Surface *kuva; -> SDL_Surface *kuva[10];

main:

SDL_Delay(10);


for(int i=0;i<10;i++)  //Surfaseiden vapautus.. ONKO OIKEIN?
{
   SDL_FreeSurface(kuva[i]);
}

piirrä:

void Piirra(int objekti, int X, int Y){    //kuvien piirto


  SDL_Rect alue; // mille alueellä näyttöä kuva piirretään
  alue.x = X; // koordinaatit
  alue.y = Y;


  SDL_BlitSurface(kuva[objekti], NULL, screen, &alue);


}

tkok [15.08.2008 17:23:29]

#

Pdän kuvat selkeyden vuoksi suoraan kovalevyn pohjalla. En tiedä miksi tulee se /-merkki siihen alkuun mutta ei toimi ilman.

vehkis91 [15.08.2008 17:54:52]

#

Mulle on ihan sama mistä ne kuvat lataa.. Laita tuohon lataus funktioon se oikea polku ja kerro sitten toimiko se ohjelma.

tkok [15.08.2008 18:31:38]

#

Joo nyt toimii täysillä, kiitos avuista.

vehkis91 [15.08.2008 18:33:01]

#

No hyvä. :D


Sivun alkuun

Vastaus

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

Tietoa sivustosta