Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Hyppääminen C++

Sivun loppuun

MIB [01.10.2009 15:58:18]

#

Terve

Tässä tuli mieleen, että miten saisin ukon "hyppäämään" kun välilyöntiä painetaan. Helpolla muutan sen ukon kohtaa, mutta miten sen saa näyttämään hyppäämiseltä? Jos ukon sijainti on x = 50, y = 200, niin jos hyppy olisi 20px korkea, niin miinustettaisiin y:n arvoa kahdellakymmenellä ja sitten hetken päästä lisättäisiin se takaisin kun laskeudutaan. Se vaan olisi tyhmän näköistä.

Eli, millaisella silmukalla sen saisi näyttämäänkin hypyltä?

for(int i = 0; i < 40; i++) {
     piirra_ukko(x++, y++);

     if(i > 20) {
         piirra_ukko(x--, y--);
     }
     Sleep(60);
}

Tältä näyttää sellainen pongahdus ylös-alas.

Grez [01.10.2009 16:13:55]

#

No periaatteessahan voit antaa sille ukolle alkuvauhdin ylöspäin ja integroida putoamiskiihtyvyyden ajalla.

Eli siis anna ukolle paikan X ja Y lisäksi nopeus vaakaan ja pystyyn sekä kiihtyvyys pystyyn. Jos päivität ruutua vaikka 50 krt/s niin pystykiihtyvyys voisi olla 25px/s^2.

Eli kun painetaan hyppynappia ja ukkosi on maan pinnalla niin annat sille vaikka 20px/s nopeuden ylöspäin. Sitten joka kierroksella (eli 50krt/s) vähennät nopeutta 0,25px/s. Kun ukko on päässyt hypyssä lakikorkeuteen, niin nopeus ylöspäin muuttuu negatiiviseksi eli alaspäin. Kun ukkosi törmää maahan, niin muutat vaakanopeuden nollaksi.

jalski [01.10.2009 16:16:26]

#

Alla olevasta linkistä löydät tutoriaaleja Nintendo DS - ohjelmointiin käyttäen PAlib-kirjastoa. Katso sivun vasemmasta reunasta kohdasta Platform Game.

Juu ja tiedän, ettet nyt ohjelmoi Nintendo DS:lle, mutta samat perusajatukset toimivat silti...

http://www.palib.info/wiki/doku.php

MIB [01.10.2009 16:28:39]

#

Grez kirjoitti:

No periaatteessahan voit antaa sille ukolle alkuvauhdin ylöspäin ja integroida putoamiskiihtyvyyden ajalla.

Eli siis anna ukolle paikan X ja Y lisäksi nopeus vaakaan ja pystyyn sekä kiihtyvyys pystyyn. Jos päivität ruutua vaikka 50 krt/s niin pystykiihtyvyys voisi olla 25px/s^2.

Eli kun painetaan hyppynappia ja ukkosi on maan pinnalla niin annat sille vaikka 20px/s nopeuden ylöspäin. Sitten joka kierroksella (eli 50krt/s) vähennät nopeutta 0,25px/s. Kun ukko on päässyt hypyssä lakikorkeuteen, niin nopeus ylöspäin muuttuu negatiiviseksi eli alaspäin. Kun ukkosi törmää maahan, niin muutat vaakanopeuden nollaksi.

Menee pää pyörälle noista. Pakko sanoa, että ymmärsin mitä tarkoitat mutta ei ole hajuakaan toteutuksesta. Pitänee miettiä vielä, ja esimerkki voisi helpottaa.*


(*Jos joku meinaa jotain laittaa, niin ei mielellään mitään valmista vaan soveltamista pitäisi olla oppimisen vuoksi. :D)

Edit. Muuten, miten voisin laskea kuinka kauan ohjelma on ollut käynnissä ja tulostaa sen komentoriville?

goala [01.10.2009 16:43:21]

#

Käytä klassista sini-käyrää ;)

Torgo [01.10.2009 16:43:46]

#

No jotenkin tähän tyyliin:

silmukka jota ajetaan n krt/s:
    jos (hyppy):
        nopeus_y = alkunopeus_y
        ilmassa = kyllä

    jos (ilmassa):
        paikka_y += nopeus_y
        nopeus_y -= putoamiskiihtyvyys
        jos (paikka_y <= maan_taso):
            ilmassa = ei
            paikka_y = maan_taso
            nopeus_y = 0

    // + x-suunnan käsittelyt normaalisti

    piirra_ukko(paikka_x, paikka_y)

Edit. ja tietysti tuo milloin hyppy alkaa täytyy tarkastaa itse koodissa vähän paremmin kuin tuo pseudo antaa ymmärtää, ettei nopeudelle anneta jatkuvasti lähtönopeutta => ukko lähtee lentoon

MIB [01.10.2009 17:06:16]

#

Hypätessä myös pitäisi tietää, että hypätäänkö vasemmalle, ylös vai oikealle.
Jos esimerkiksi hyppy kantaa 20 pikseliä haluttuun suuntaan (if(napit[SDLK_RIGHT]) suunta = oikealle;).

En ole vielä koulussa käsitellyt mitään nopeuksiin viittaavaa, joten menee vähän ohi nuo jutut. Nyt tiedän miltä tuntuu olla kunnolla "pulassa"... kun ei tiedä mitä pitää tehdä.

Grez [01.10.2009 17:25:28]

#

Mun mielestä hypätessä ei ole olennaista tietää mihin suuntaan hypätään. Ukkelin vaakanopeus voi ihan hyvin pysyä hypätessä muuttumattomana.

Ja eihän toi nopeus nyt mikään ihmeellinen asia ole. Itsekin varmaan tiedät mitä tapahtuu jos meet vaikka pyörällä 20 km/h johonkin suuntaan. Ja 7. luokallahan fysiikassa opetetaan myös kiihtyvyys.

Metabolix [01.10.2009 20:06:23]

#

Jos matemaattiset taitosi ovat hyvällä mallilla, voit käydä vaikka lainaamassa kirjastosta lukion fysiikankirjoja. Matematiikkaa tarvitaan lähtökohtaisesti kertolaskun verran, mutta lisäksi on hyvä hallita laskusäännöt ja yhtälöiden ratkaisemisen perusasiat. Ensimmäinen fysiikankurssi kannattaa lukea, jotta pääsee vähän jyvälle jutusta, ja yksinkertaisen peliohjelmoinnin kannalta olennaisimmat ovat sen jälkeen neljäs (etenemisliike) ja viides (pyörimisliike ja painovoima).

Lisäksi pelejä tehdessä kannattaa tuntea matematiikkaoppaissa esitellyt asiat: Trigonometriasta on hyötyä heti, kun siirrytään ruudukosta vapaampaan liikkumiseen, ja vektorit helpottavat monia liike- ja törmäyslaskuja.

Lukion fysiikassa ei käsitellä lainkaan kolmiulotteisia tilanteita, ja kaksiulotteisissakaan ei käytetä vektoreita, joten näiden suhteen ei auta kuin etsiä itse tietoja ja soveltaa kaavoja. Ainoa olennainen muutos kolmiulotteisuuteen siirryttäessä tapahtuu pyörimisliikkeessä, kun kappale ei enää pyöri myötä- tai vastapäivään vaan jonkin akselin ympäri. :)

MIB [02.10.2009 13:45:37]

#

Grez kirjoitti:

Mun mielestä hypätessä ei ole olennaista tietää mihin suuntaan hypätään. Ukkelin vaakanopeus voi ihan hyvin pysyä hypätessä muuttumattomana.

Ja eihän toi nopeus nyt mikään ihmeellinen asia ole. Itsekin varmaan tiedät mitä tapahtuu jos meet vaikka pyörällä 20 km/h johonkin suuntaan. Ja 7. luokallahan fysiikassa opetetaan myös kiihtyvyys.

Yleensä peleissä jos tarvitsee hypätä, niin pitää päästä jonnekkin tiettyyn paikkaan hyppäämällä. Eihän ole järkeä paikallaan hyppiä.

Voisitko näyttää, miten sen sitten saa "hyppäämään"? Minusta on jotenkin ihmeellistä, että olen tekemässä jotain mitä en vielä osaa. Suurin osa tähän mennessä tulleista "taidoistani" on tullut soveltamalla kaikenlaisia koodeja, mitä netistä löytyy. Sanonta "Kuva kertoo enemmän kuin tuhat sanaa." voisi olla ohjelmointiympäristössä "Soveltaminen opettaa enemmän kuin kymmenen opasta.".

Jalmari91 [02.10.2009 13:57:45]

#

MIB kirjoitti:

Grez kirjoitti:

Mun mielestä hypätessä ei ole olennaista tietää mihin suuntaan hypätään. Ukkelin vaakanopeus voi ihan hyvin pysyä hypätessä muuttumattomana.

Ja eihän toi nopeus nyt mikään ihmeellinen asia ole. Itsekin varmaan tiedät mitä tapahtuu jos meet vaikka pyörällä 20 km/h johonkin suuntaan. Ja 7. luokallahan fysiikassa opetetaan myös kiihtyvyys.

Yleensä peleissä jos tarvitsee hypätä, niin pitää päästä jonnekkin tiettyyn paikkaan hyppäämällä. Eihän ole järkeä paikallaan hyppiä.

Voisitko näyttää, miten sen sitten saa "hyppäämään"? Minusta on jotenkin ihmeellistä, että olen tekemässä jotain mitä en vielä osaa. Suurin osa tähän mennessä tulleista "taidoistani" on tullut soveltamalla kaikenlaisia koodeja, mitä netistä löytyy. Sanonta "Kuva kertoo enemmän kuin tuhat sanaa." voisi olla ohjelmointiympäristössä "Soveltaminen opettaa enemmän kuin kymmenen opasta.".

Siis minä ainakin käsitin näin, että sen nopeuden ei tarvitse muuttua hyppäämisestä, vaan jos se "ukkeli" juoksee, niin se juoksun vaaka vektori tulee mukaan siihen hyppyyn ja pysyy muuttumattomana ellei törmätä mihinkään. Eli jos hypätään niin ainoastaan korkeus muuttuu.

Teuro [02.10.2009 14:21:25]

#

Eli toisin sanoen voit käyttää "vaakasuoraa heittoliikettä" kuvaamaan hyppyä. Tuossa on vielä valmis hakusana esim. googlelle. Toivottavasti sinulle alkeellinen fysiikka on jonkun verran tuttua.

vx = vaakasuora nopeus
vy = pystysuora nopeus
v = nopeus jolla liikutaan
s = matka

alfa = kulma jossa hypätään (etumerkillinen radiaaneissa)

vx = v * cos(alfa)
vy = v * sin(alfa)

maksikorkeus saadaan nousuajasta lakikorkeuteen (vy = 0)
vy - g * t = 0

Tuosta kun ratkaisee t:n, niin voidaan laskea matka y-suunnassa
t = vy / g

MIB [02.10.2009 16:12:59]

#

Tuli veljen kanssa kaameat naurut, kun onnistuin sen saamaan "hyppäämään" toisin sanoen jummppamaan. :D Nyt sen liike on kyykkyyn ylös, kyykkyyn ylös.

void hyppy(int sijainti_x, int sijainti_y) {
    int korkeus = sijainti_y;
    for(int i = 0; i < 100; i++) {
        if(i <= 50)
            korkeus--;
        else korkeus++;

        piirra("./img/ukkeli.bmp", sijainti_x, korkeus);
        Sleep(4);
    }
}

Näin se sitten jumppaa. :D Ongelma on se, että miten saisin tuon hävittämään vanhan kuvan joka kierroksella? Jossain joku sanoi, että ei mitenkään, vaan se pitää peittää, mutta pitääkö paikkaansa?

Metabolix [02.10.2009 16:30:00]

#

Kyllä, pitää paikkansa.

Ennen kuin kysyt, miten muun pelin saisi pyörimään hypyn aikana, kannattaa tutustua koodivinkkiin reaaliaikaisen pelin rakenteesta. Siellä on myös tätä liike- ja kiihtyvyysasiaa. (Jos vinkki on liian vaikea ymmärtää, annan vanhan neuvon: tee jotain helpompaa ensin, jotta taitosi karttuisivat tarvittavalle tasolle. Ohjelmointia voi hyvin verrata musiikkiin: ei pianonsoiton harjoittelua voi aloittaa Chopinin Vallankumousetydistä, vaan pitää kärsivällisesti aloittaa alkeista.)

MIB [02.10.2009 16:31:57]

#

Okei, eli lättäilen sinne valkoisia ruutuja aina kyseisen kuvan paikalle ja piirrän seuraavan.

Ei, ei ole vaikeuksia saada muuta peliä rullaamaan samaa aikaa. Itse asiassa olen sen jo tehnytkin. =)

Ps. Olen lukenut koodivinkkisi.

Metabolix [02.10.2009 16:45:57]

#

Valkoinen ruutu kannattaa muuten tehdä SDL_FillRect-funktiolla, ei siis turhaan ladata kuvaa sitä varten. Useinhan pelissä on jonkinlainen tausta, joka piirretään joka kierroksella uudelleen, jolloin ei tuollaisiakaan ongelmia tule.

MIB [02.10.2009 17:06:13]

#

Niin, no katsotaampas sitten noin. =)

Täällä on käännetyt versiot kahdella tyylillä. Ensimmäisessä ladataan tausta aina uudelleen ja toisessa vain kerran. Selvä ero :D

jalski [02.10.2009 17:08:06]

#

Tutustuitko muuten aiemmin postittamaani linkkiin? Hiukan soveltamalla saisit varmaan ohjeiden pohjalta kasattua jotain testiohjelmaa.

Pyöriikö täällä muuten ketään, joka olisi harrastellut ohjelmointia Nintendo DS alustalle? Upea pieni laite, hardwarella tuki useammalle taustalle (helppo toteuttaa parallax scrollaus), spriteille (piirto, rotatointi, flippaus, clipping), hyvät ääniominaisuudet, 3D-tuki, Wifi ja muita herkkuja...

MIB [02.10.2009 18:21:53]

#

Muuten, koska samaan ohjelmaan tulee myös hiiritoimintoja, niin kysyisin tästä.

Tein tälläisen "piirtopöydän" harjoituksen vuoksi, mutta nähtävästi tuo silmukka ei toista itseään tarpeeksi usein, koska jokainen pikseli ei ole kiinni toisissaan.

#include <SDL/SDL.h>
#include <string>
#include <windows.h>

using namespace std;
SDL_Surface *ruutu;

void piirra(string polku, int left, int top) {
    SDL_Surface *kuva = SDL_LoadBMP(polku.c_str());
    SDL_Rect kohta = {left, top};
    SDL_BlitSurface(kuva, 0, ruutu, &kohta);
    SDL_FreeSurface(kuva);
    SDL_Flip(ruutu);
}


int main(int argc, char **argv) {
    SDL_Init(SDL_INIT_VIDEO);
    ruutu = SDL_SetVideoMode(700, 400, 32, SDL_DOUBLEBUF);


    SDL_WM_SetCaption("Pikselipiirtopöytä", "Pikselipiirtopöytä");

    piirra("pohja.bmp", 0, 0);

    bool piirto = true;
    int hiiri, x, y;

    while(piirto == true) {
        SDL_PumpEvents();
        const Uint8 * const napit = SDL_GetKeyState(0);

        if(napit[SDLK_ESCAPE]) piirto = false;
        hiiri = SDL_GetMouseState(&x, &y);

        if(hiiri & SDL_BUTTON(1)) {
            piirra("piste.bmp", x, y);
        } else if(hiiri & SDL_BUTTON(3)) {
            piirra("kumi.bmp", x, y);
        }
    }
    SDL_Quit();
    return 0;
}

Metabolix [02.10.2009 18:24:58]

#

Hieman tasaisemman viivan saisit ehkä, jos käsittelisit viestit sillä toisella tavalla (SDL_PollEvent-silmukalla). Lopulta kyse ei kuitenkaan ole silmukan toistonopeudesta vaan siitä, että kun hiiri liikkuu nopeasti, se ei kulje joka pikselin kautta vaan hyppää pitkiäkin matkoja. Voit nähdä tämän, kun heilutat hiirtä ruudulla: kursori hyppii jopa monta senttiä kerrallaan.

MIB [02.10.2009 18:28:26]

#

Jep, niimpä se näyttääkin menevän. Auttoi kyllä vähän tuo SDL_PollEvent, mutta ei tarpeeksi.

Miten esimerkiksi Paint pystyy käsittelemään kaikki pikselit?

Legu [02.10.2009 18:33:07]

#

MIB kirjoitti:

Miten esimerkiksi Paint pystyy käsittelemään kaikki pikselit?

Se piirtää viivan aina edellisen ja nykyisen hiiren koordinaatin välille luultavasti Bresenhamin algoritmilla tai vastaavalla.

MIB [02.10.2009 18:34:47]

#

Osaisitko kertoa, että miten saisin sen tällä C++:lla toimimaan? =) Nuo esimerkit taisivat olla Delphiä.


Muuten, ja miten saan kursoriksi xx.bmp kuvan jos oikea näppäin on pohjassa (hiiressä, if(hiiri & SDL_BUTTON(3)) { kursori = kuva.bmp; })?

Metabolix [02.10.2009 19:25:14]

#

Viivan piirrosta: tuon verran pitäisi kyllä osata lukea yksinkertaista pseudokoodia.

Kursorista: käytännössä joudut piilottamaan oikean kursorin (SDL_ShowCursor(SDL_DISABLED)) ja piirtämään haluamasi kuvan SDL_BlitSurfacella. Jos kursorisi sattumalta olisi mustavalkoinen ja pieni, voisit hoitaa asian tuolla sivulla mainituilla muilla funktioilla, mutta se on vaikeampaa ja vaatii tosiaan aivan tietynlaisen kursorin.

MIB [02.10.2009 20:53:11]

#

Metabolix kirjoitti:

Viivan piirrosta: tuon verran pitäisi kyllä osata lukea yksinkertaista pseudokoodia.

Kaikki välttämättä eivät ymmärrä.

Metabolix kirjoitti:

Kursorista: käytännössä joudut piilottamaan oikean kursorin (SDL_ShowCursor(SDL_DISABLED)) ja piirtämään haluamasi kuvan SDL_BlitSurfacella. Jos kursorisi sattumalta olisi mustavalkoinen ja pieni, voisit hoitaa asian tuolla sivulla mainituilla muilla funktioilla, mutta se on vaikeampaa ja vaatii tosiaan aivan tietynlaisen kursorin.

Sain kursorin pois käytöstä ikkunassa, ja onnistuin myös saamaan reunatkin siitä pois. En kuitenkaan ymmärtänyt, että miten saisin sen kursorin toiseksi.

vehkis91 [02.10.2009 21:10:26]

#

siis lataat sen uuden kursorin kuvan ja sitten pääsilmukassa piirrät sen kuvan hiiren koordinaatteihin.

Metabolix [02.10.2009 21:22:36]

#

MIB kirjoitti:

Metabolix kirjoitti:

Viivan piirrosta: tuon verran pitäisi kyllä osata lukea yksinkertaista pseudokoodia.

Kaikki välttämättä eivät ymmärrä.

Mikä rivi koodissa tuottaa vaikeuksia?

Zeeli [02.10.2009 21:25:26]

#

Itse toteuttaisin piirron tällä tavalla:

jokaisella kierroksella {
    hiiren_uusi_sijainti = HaeHiirenSijainti();

    piirräViiva(hiiren_vanha_sijainti, hiiren_uusi_sijainti,);

    hiiren_vanha_sijainti = hiiren_uusi_sijainti;
}

MIB [02.10.2009 21:36:15]

#

Vehkis: Se ei toimisi, koska kuva jäisi ruudulle tähän kohtaan.

Metabolix: Tuolla on funktioita suurimmakseen osakseen koko koodi täynnä, joista ei ole hajuakaan mitä ne tekevät.

Zeeli: Perjaatteessa se näin minulla onkin, mutta mitä laitetaan piirräViiva funktioon?

Kuitenkin, jos toteutatte yksinkertaisen piirto-ohjelman, joka toimii tällä Bresenhamin viiva algometrillä, niin se ei kuitenkaan toimi niin hyvin. Jos tekee testin:

Valitsee kumpaankin ohjelmaan yhden pikselin piirrettävän pikselin (siis paksuus yhden pikselin). Sitten vedetään hiiri ohjelman toisesta päästä mahdollisimman nopeasti toiseen mutkan kauttaa (pyörittelee hiirtä ruudulla), niin Paintilla on pyöreämmät kulmat kuin omassa ohjelmassa eli tulos olisi sellainen, että Paintissa on jotain muuta erillaista miten se piirtää viivan. Vai sanooko joku vastaan?

vehkis91 [02.10.2009 21:47:00]

#

EDIT: sanoin, että pääsilmukassa ja luonnollisesti aina ennen kuvan piirtoa haet hiiren uuden sijainnin!

Koitas tätä:

template <class T> void swap ( T& a, T& b );

void line(int x0, int x1, int y0, int y1)
{
	bool steep = abs(y1 - y0) > abs(x1 - x0);

	if(steep)
	{
		swap(x0,y0);
		swap(x1,y1);
	}
	if(x0 > x1)
	{
        swap(x0, x1);
        swap(y0, y1);
	}

	int deltax = x1 - x0;
	int deltay = abs(y1 - y0);

	int error = deltax / 2;

	int ystep;

	int y = y0;

	if(y0 < y1)
		ystep = 1;
	else
		ystep = -1;

	for(int x = x0; x < x1; x++)
	{
		if(steep)
            //Piirra piste....
			plot(x,y);
		else
            //Piirra piste....
			plot(y,x);

		error = error - deltay;

		if(error < 0)
		{
			y += ystep;
			error += deltax;
		}
	}
}

//////MAIN ja joitan muuta...


template <class T> void swap ( T& a, T& b )
{
  T c(a); a=b; b=c;
}

Metabolix [02.10.2009 21:48:57]

#

MIB: useimmat rivit ovat sijoitusrivejä, ja lisäksi on pari ihan tavallista ehtoa ja silmukkaa. Lisäksi swap-funktio vaihtaa kahden arvon paikkaa; C++ sisältää myös sellaisen (#include <algorithm>, std::swap(a, b);).

vehkis91: Tyhmää toteuttaa turhaan uudestaan standardikirjaston funktioita.

MIB [02.10.2009 21:51:47]

#

Koitin tätä ja saan error: `plot' was not declared in this scope.

Metabolix [02.10.2009 21:56:02]

#

Luepa se koodi sitten ja ajattele hetki. Mistä se koodi tietäisi, miten juuri sinun ohjelmassasi piirretään pikseleitä? Ei mistään, siksi se käyttää kuvitteellista funktiota plot(x,y), joka piirtää yhden pisteen.

Legu [02.10.2009 21:56:18]

#

MIB kirjoitti:

Valitsee kumpaankin ohjelmaan yhden pikselin piirrettävän pikselin (siis paksuus yhden pikselin). Sitten vedetään hiiri ohjelman toisesta päästä mahdollisimman nopeasti toiseen mutkan kauttaa (pyörittelee hiirtä ruudulla), niin Paintilla on pyöreämmät kulmat kuin omassa ohjelmassa eli tulos olisi sellainen, että Paintissa on jotain muuta erillaista miten se piirtää viivan. Vai sanooko joku vastaan?

Tarkoittaako tuo nyt sitä, että sait algoritmin toimimaan (tai käytit valmista kirjastoa)?
Mikäli tuo oli "vain" joku hypoteesi, niin testaa äläkä arvaile.

vehkis91 [02.10.2009 21:57:00]

#

Edit: toi sun linkkis johtaa tyhjälle sivulle...

Mitäs jos vaihtaisit sen plot() tilalle oman piirtofunkkarisi?

Metabolix: Tein nopeesti nii ei käyny mieless tarkistaa, että sisältääkö c++ kyseistä funkkaria.

MIB [02.10.2009 21:59:04]

#

Eipä käynnyt mielessä, että tuo plot olisi jokin tekaistu juttu. No, hyvä että kerroit, niin sain valmiiksi.


Joku viisaampi voi sanoa, että mikä tätä vaivaa:

#include <SDL/SDL.h>
#include <string>
#include <windows.h>


using namespace std;
SDL_Surface *ruutu;

void piirra(string polku, int left, int top) {
    SDL_Surface *kuva = SDL_LoadBMP(polku.c_str());
    SDL_Rect kohta = {left, top};
    SDL_BlitSurface(kuva, 0, ruutu, &kohta);
    SDL_FreeSurface(kuva);
    SDL_Flip(ruutu);
}


void viiva(int x1, int y1, int x2, int y2) {
    int delta_x = std::abs(x2 - x1) << 1;
    int delta_y = std::abs(y2 - y1) << 1;

    // if x1 == x2 or y1 == y2, then it does not matter what we set here
    signed char ix = x2 > x1?1:-1;
    signed char iy = y2 > y1?1:-1;

    piirra("piste.bmp", x1, y1);

    if (delta_x >= delta_y)
    {
        // error may go below zero
        int error = delta_y - (delta_x >> 1);

        while (x1 != x2)
        {
            if (error >= 0)
            {
                if (error || (ix > 0))
                {
                    y1 += iy;
                    error -= delta_x;
                }
                // else do nothing
            }
            // else do nothing

            x1 += ix;
            error += delta_y;

            piirra("piste.bmp", x1, y1);
        }
    }
    else
    {
        // error may go below zero
        int error = delta_x - (delta_y >> 1);

        while (y1 != y2)
        {
            if (error >= 0)
            {
                if (error || (iy > 0))
                {
                    x1 += ix;
                    error -= delta_y;
                }
                // else do nothing
            }
            // else do nothing

            y1 += iy;
            error += delta_x;

            piirra("piste.bmp", x1, y1);
        }
    }
}


int main(int argc, char **argv) {
    SDL_Init(SDL_INIT_VIDEO);
    ruutu = SDL_SetVideoMode(700, 400, 32, SDL_DOUBLEBUF);

    //SDL_ShowCursor(SDL_DISABLE);

    SDL_WM_SetCaption("Pikselipiirtopöytä", "Pikselipiirtopöytä");

    piirra("pohja.bmp", 0, 0);


    bool piirto = true;
    bool pohjassa = false;
    int lastx, lasty;

    int hiiri, x, y;
    string kummi = "kumi.bmp";

    int hiiri2, xxx, yyy;
    while(piirto == true) {
        SDL_Event tapahtuma;
        SDL_PollEvent(&tapahtuma);


        if(napit[SDLK_ESCAPE]) piirto = false;
        hiiri = SDL_GetMouseState(&x, &y);

		// Tässä on pari määrittelyä, jotka eivät liity asiaan

        lastx = x;
        lasty = y;

        if(hiiri & SDL_BUTTON(1)) {
            viiva(lastx, lasty, x, y);
        } else if(hiiri & SDL_BUTTON(3)) {
            piirra(kummi, x, y);
        } else if(hiiri & SDL_BUTTON(2)) {
            piirra("pohja.bmp", 0, 0);
            kummi = "kumi.bmp";
        }
    }
    SDL_Quit();
    return 0;
}

vehkis91 [02.10.2009 22:22:04]

#

Se, että sun pitäis sijoittaa x tuonne lastx muuttujaan vasta noiden ehtojen jälkeen ja y:n kanssa sama homma.

Edit: siis näin:

if(hiiri & SDL_BUTTON(1)) {
    viiva(lastx, lasty, x, y);
} else if(hiiri & SDL_BUTTON(3)) {
    piirra(kummi, x, y);
} else if(hiiri & SDL_BUTTON(2)) {
    piirra("pohja.bmp", 0, 0);
    kummi = "kumi.bmp";
}

lastx = x;
lasty = y;

Metabolix [02.10.2009 22:27:43]

#

Muutenhan siis viivan piirron aikaan lastx ja lasty ovat samat kuin x ja y, jolloin mitään viivaa ei tule (tulee piste).

Legu [02.10.2009 22:30:02]

#

Just joo, epäilinkin jotain tällaista esitystä...
Aiotko tosiaan tehdä noita kuvia 2^24 = 16777216 kappaletta, jotta saat kaikki värit (24-bittinen) käyttöön?
Turha ihmetellä, jos piirroksesta tulee viivamainen, kun kuvat ladataan ja vapautetaan joka kerta, kun ne piirretään, mikä hidastaa ohjelman toimintaa huomattavasti. Tee nyt vain niin kuin oppaassa neuvotaan, äläkä yritä olla "fiksu".

vehkis91 [02.10.2009 22:37:09]

#

Edit: lisätty koodia...

Eli lataa, kaikki kuvat ennen pääsilmukkaa muistiin (jokaiselle oma SDL_surface)
ja sitten muutat piirtofunktiota siten, että se ottaa parametrikseen SDL_surfacen sen stringin tilalla.

Ja sitten pääsilmukan jälkeen vapautat kaikki surfacet.

piirtofunkkari korjattuna:

void piirra(SDL_Surface *kuva, int left, int top)
{
    SDL_Rect kohta = {left, top};
    SDL_BlitSurface(kuva, 0, ruutu, &kohta);
}

Tuon SDL_Flip() funktion sijoitat pääsilmukan loppuun. Loput muutokset saatkin tehdä itse.

MIB [02.10.2009 22:58:47]

#

Kiitosta taas neuvoista... Muuten, miten saisin valittua ohjelmassa mikä kuva laitetaan taustalle? Eli, miten saan tuollaisen browse jutun, mistä voi valita kuvan jonka ohjelma laittaa sitten taustakuvaksi? Entä, miten saisin piirroksen tallennettua?

Metabolix [02.10.2009 23:05:57]

#

SDL_SaveBMP-funktiolla voi tallentaa SDL_Surfacen sisällön tiedostoon. (Googleta parametrit.)

Tiedostolistaukset ovat hankalia juttuja ja valitettavasti toimivat eri käyttöjärjestelmissä hyvinkin eri tavoilla.

Legu [02.10.2009 23:10:23]

#

Tallennus onnistuu SDL_SaveBMP:llä.

SDL:ssä ei ole mitään valmista GUI-systeemiä, eli joudut siis piirtämään kaiken itse pikselipohjaisena, kuvilla ja tekstillä (josta et tule selviytymään nykyisillä taidoillasi). Itse "browseen" tarvitaan järjestelmäriippuvaisia funktioita, eli SDL tai C++:n standardikirjasto eivät sisällä tuota ominaisuutta.

Kannattaa varmaan tehdä niin, että ladattava tiedosto annetaan komentoriviparametrina. Pelkän tekstikentänkään teko, johon kuvan sijainnin voisi "graafisessa tilassa" kirjottaa, ei ole niin helppoa kuin ehkä kuvittelet.


Sivun alkuun

Vastaus

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

Tietoa sivustosta