Koetan näitä SDL juttuja tässä sisäistää ja nyt tuli ongelma vastaan.
Kun näppäintä painetaan käynnistää se ajastimen (SDL_AddTimer()).
Ajastin kutsuu sekunnin välein funktiota joka arpoo piirettävälle kuviolle uudet x ja y koodrinaatit.
x1 = xalkuArvo + rand() % 400; Y1 = yalkuArvo + rand() % 400; x2 = x1 + 40; Y2 = Y1 + 40; return interval;
Tämän jälkeen pääohjelman (main)pääloopissa suoritetaan piirtäminen (rectangleRGBA()) ja sen jälkeen flipataan näyttö (SDL_Flip();).
VideoModen asetuksissa olen käyttänyt SDL_DOUBLEBUF määritystä. Eikö tuon pitänyt poistaa välkkyminen?
Homma toimii muuten kuten ajattelinkin eli kuvio piirretään aina satunnaiseen paikkaan näytöllä mutta ennen varsinaista lopullista piirtämistä kuvio vilahtaa monessa kohdassa näyttöä ennen kuin "pysähtyy".
Aivan kuin kuviota piirrettäisiin randomisti vähän sinne sun tänne ennen oikeaa paikkaa...
Koetin googlestakin sanoilla SDL flickering etsiä vastausta mutta en löytänyt vastausta :(
Todennäköisimmin vika on vain omassa koodissasi, eli varmaankin piirrät sen vahingossa moneen kertaan. Tulosta piirtämisen yhteydessä jotain debug-tietoja, niin pääset ehkä eteenpäin.
static int piirtokerta; ++piirtokerta; fprintf(stderr, "%7d: %5d\n", (int) SDL_GetTicks(), piirtokerta);
Jos vika olisi kaksoispuskuroinnissa, kuva piirtyisi oikeaan kohti mutta ruudulla saattaisi välillä näkyä keskeneräinen piirros (ts. ruutu saattaisi päivittyä missä tahansa välissä eikä vain SDL_Flip-funktion kohdalla).
Ei aukea nyt tämä ongelma :(
Mielestäni piirrän kuvion vain kerran...
Koetin tuota Metabolixin ehdottamaa tiedostoon tulostusta ja kyllähän sinne tiedostoon tulikin lukuja, mutta ei oikein kirkastunut tuonkaan avulla :(
Lisäksi koetin aivan normaalilla debuggauksella mutta en saanut ohjelmaa siirtymään ajastimen kohtaan, se kun olisi vaatinut näppäimen painalluksen.
Joten kokeilin debugata ilman näppäinpainallusta jolloin ohjalman suoritus kyllä meni ajastimen kutsumaan funktioon ja jäi sinne pyörimään, jolloin arvotaan aina uudet koordinaatit.
Olen koettanut jos jonkinlaista viritystä funktion sisällä mutta ei ole auttanut.
Tässä vielä viritykseni tarkasteltavaksi.
#include <SDL/SDL.h> #include <SDL/SDL_gfxPrimitives.h> #include<stdlib.h> #include<time.h> Uint32 liiketta(Uint32 interval, void *param); int x1, Y1, x2, Y2; int main(int argc, char *argv[]) { int ohjelmaKaynnissa; Uint8* nappi; SDL_Surface *naytto; SDL_Event tapahtuma; SDL_TimerID ajastin; SDL_Init( SDL_INIT_VIDEO |SDL_INIT_TIMER ); naytto = SDL_SetVideoMode(800, 600,0,SDL_HWSURFACE | SDL_DOUBLEBUF ); SDL_WM_SetCaption( "Testi", 0 ); ohjelmaKaynnissa = 1; /*neliölle alkuarvot*/ x1 = 210; Y1 = 110; x2 = 250; Y2 = 150; srand(time(NULL)); while(ohjelmaKaynnissa) { if (SDL_PollEvent(&tapahtuma)) { if (tapahtuma.type == SDL_QUIT) { ohjelmaKaynnissa = 0;//false } if( tapahtuma.type == SDL_KEYDOWN ) { if( tapahtuma.key.keysym.sym == SDLK_ESCAPE ) { SDL_RemoveTimer(ajastin); ohjelmaKaynnissa = 0; } } } nappi = SDL_GetKeyState(NULL); if( nappi[SDLK_s] ) { ajastin = SDL_AddTimer(1000,liiketta,NULL); } SDL_FillRect(naytto, NULL, SDL_MapRGB(naytto->format, 0, 0, 0)); boxRGBA(naytto, x1, Y1, x2, Y2, 255, 0, 0, 255); SDL_Flip(naytto); } SDL_Quit(); return 0; } Uint32 liiketta(Uint32 interval, void *param) { x1 = 210 + rand() % 400; Y1 = 110 + rand() % 400; x2 = x1 + 40; Y2 = Y1 + 40; return interval; }
SDL_PollEvent-funktiota kuuluisi kutsua silmukassa (eli vaihtaa iffin tilalle while), jotta aina käsiteltäisiin kaikki jonossa olevat viestit eikä vain ensimmäistä.
Pääsilmukkasi ehtii luultavasti pyörähtää kymmeniä kertoja sinä aikana, kun nappi on pohjassa, joten asetat kymmeniä ajastimia. Ajastin pitäisi luoda ohjelman alussa, tai sen asetus pitäisi käsitellä samalla tavalla kuin tuo poisto eli SDL_PollEvent-silmukassa.
Niistä tulostetuista luvuista ensimmäinen on aina aikaleima millisekunteina, joten siitä voisit nähdä, että rivejä tulee aivan liikaa (pitäisi kai tulla yksi sekunnissa?) ja aivan liian tiheästi (ehkä muutaman sekunnin sadasosan välein).
Kiitos ohjauksesta oikeaan suuntaan :)
Nyt toimii !!!!
Ja mitä niihin tulostettuihin riveihin tulee, niitä todellakin tuli aivan mahdottomasti ;)
Mitenkäs muuten noiden timerien kanssa SDL:ssä on, jos haluan esim. tuon kuvion liikkumisen kanssa suorittaa jotain muuta tehtävää samaan aikaan, onnistuuko?
Voi olla montakin ajastinta, kuten äsken käytännössäkin todistit. Niitä ei kuitenkaan pidä käyttää väärin.
Ajastinta pitäisi käyttää siinä tapauksessa, että ohjelma odottaa SDL_WaitEvent-funktiolla käyttäjän toimintaa ja halutaan siitä huolimatta tehdä taustalla jotain säännöllisesti. Esimerkiksi sähköpostiohjelma tavallisesti vain odottaa käyttäjän syötettä mutta tarkistaa kuitenkin postit muutaman minuutin välein.
Jos on tarkoitus tehdä reaaliaikainen ohjelma (esim. peli), nuo ajastimet ovat siihen väärä ratkaisu. Jos on tuollainen jatkuvasti pyörivä pääsilmukka, "ajastin" pitäisi toteuttaa siinä itse:
const Uint32 aikavali = 1000; Uint32 ajastin = 0; while (kaynnissa) { const Uint32 nyt = SDL_GetTicks(); // Hoidetaan viestit... :) while (SDL_PollEvent(&e)) { if (e == tarkea_tapahtuma) { ajastin = nyt + aikavali; } else if (e == lopetustapahtuma) { ajastin = 0; } } // Hoidetaan ajastimen hommat. // Taas on while siltä varalta, että ajastimen pitäisi toimia esimerkiksi // 100 kertaa sekunnissa mutta pääsilmukka ehtiikin toimia vain 30 kertaa. while (ajastin != 0 && ajastin <= nyt) { tee_jotain(); ajastin += aikavali; } }
Metabolix kirjoitti:
Ajastinta pitäisi käyttää siinä tapauksessa, että ohjelma odottaa SDL_WaitEvent-funktiolla käyttäjän toimintaa ja halutaan siitä huolimatta tehdä taustalla jotain säännöllisesti.
Jos on tarkoitus tehdä reaaliaikainen ohjelma (esim. peli), nuo ajastimet ovat siihen väärä ratkaisu. Jos on tuollainen jatkuvasti pyörivä pääsilmukka, "ajastin" pitäisi toteuttaa siinä itse:
OK, koetetaan pitää mielessä. Kiitos taas avusta.
Aihe on jo aika vanha, joten et voi enää vastata siihen.