Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: SDL ja uusi kuva

Sivun loppuun

FaCo [22.08.2006 18:41:41]

#

moi.

Minulla olisi sellainen kysyymys, että mitenkä voisi tehdä koodin, joka piirtää napista painattaessa uuden kuvan ruudulle ja liikuttaa sitä ylöspäin?

tgunner [22.08.2006 18:44:11]

#

No teet niin, että luot silmukan, joka piirtää kuvan kohtaan (kuvax, kuvay). Piirtämisen jälkeen sitten luet näppäinpainallukset -> jos painetaan ylöspäin niin vähennetään kuvay:n arvoa. Yksinkertaista.

Ohjeet tähän löydät Putkan SDL-oppaasta.

FaCo [23.08.2006 15:41:26]

#

Ilmeisesti ymmärsit asian väärin :D. Kyllä minä tuon nyt osaan. Tarkoitus olisi, että se piirtää aina uuden kuvan ja alkaa liikuttamaan sitä ylöspäin. Siis ainakun nappia painetaan piiretään uusi kuva.

Megant [23.08.2006 16:10:47]

#

https://www.ohjelmointiputka.net/oppaat/opas.php?tunnus=sdl3

Tuossahan on tuollainen esimerkki, jonka kaltaista ilmeisesti yrität toteuttaa?

tgunner [23.08.2006 16:12:45]

#

Ai siis niin. mörr, epäselvä kysymys, buu

FaCo [23.08.2006 18:16:33]

#

Ei todellakaan tarkoita mitään tuolaista :P. Noh, tätä ajamaani tekniikkaa voisi käyttää vaikka ammuttaessa. Eli aina kun painetaan ampumis nappia luodaan uusi panos ja asetetaan se tiettyy paikkaan ja sitten se sitä aletaan liikuttamaan eteenpäin.

Megant [23.08.2006 20:47:11]

#

Öh, aletaan liikuttamaan eteenpäin? o_O
Mites ajattelit liikuttaa sitä josset muuttamalla sen koordinaatteja ja piirtämällä sen aina uudestaan?

Mazzimo [23.08.2006 22:15:39]

#

Luo oma ammusluokka. Jokaisella ammus-luokan instanssilla on oma nopeusvektorinsa, paikkavektorinsa sekä osoitin pintaan, joka halutaan piirtää paikkavektorin kohtaan. Luot ensiksi ns. "masterpinnan", jonka osoitteen jokainen ammus-luokan instanssi ottavat. Aina kun haluat luoda uuden ammuksen, luot uuden instanssin dynaamisesta muistista ja linkität sen ammuksille tarkoitettuun linkitettyyn listaan. Joka loopinkierrolla käyt listan läpi päivittäen ammuksien sijainnin (paikkavektorin) sen nopeusvektorin avulla sekä sen jälkeen piirrät ammus-olion osoittaman pinnan näytölle (yms.. muut tarkistukset, esim. ammuksen törmäys). Kun ammus-olio halutaan poistaa, poistat vain kyseisen instanssin listasta (sekä varatusta muistista).

(Toivottavasti menivät termit oikein... :P instanssi == olio (ainakin) minun kielelläni.. :D )

FaCo [24.08.2006 14:06:54]

#

Voisitteko tehdä minulle esimerkki koodin?

Teuvo Töhvelö [24.08.2006 19:43:33]

#

Paljon parempi on, jos teet koodin itse. Siinä oppii mukavasti asioita, kun taas toisten koodeja kopioimalla menee pää sekaisin eikä ohjelmoinnista tule mitään. Vinkkinä kuitenkin neuvoisin käyttämään noiden linkitettyjen listojen sijasta taulukoita, koska se on aluksi helpompaa.

Luot siis ammustaulukon, jossa on vaikkapa 1000 paikkaa, ja sitten aina kun uusi ammus luodaan, sijoitat sen tuohon taulukkoon. Sitten onkin helppo käydä kaikki ammukset läpi ihan tavallisella for-silmukalla. Aluksi kannattaa ehkä tehdä koodi, joka vain luo ammuksia tasaisin väliajoin tiettyyn paikkaan ja liikuttaa niitä kaikkia sitten samaan suuntaan. Kun saat tuon toimimaan, voit yrittää saada ammuksia liikkumaan eri suuntiin (tarvitset siinä trigonometriaa).

Heikki [24.08.2006 19:51:57]

#

Tässä yksinkertainen päästä heitetty esimerkki siitä, miten ammusluokka kannattaa toteuttaa:

class Ammus {
 public:
   Ammus(float x,y,suunta,nopeus);
   void Liikuta();
   int TormaysTarkistus();
   void Piirra();
 private:
   float vx, vy; // Nopeusvektori
   float x,y; // Sijainti
// Jne jne
};

// Varsinaisessa koodissa sitten
vector<Ammus> kudit;
kudit.push_back(Ammus(5,2,4.4,2);
kudit.push_back(Ammus(2,1,1.34,2);
kudit.push_back(Ammus(78,4,6.34,2);

// Liikutetaan pateja
for (int i=0; i < kudit.size(); i++) {
  kudit[i].TormaysTarkistus();
  kudit[i].Liikuta();
}

FaCo [24.08.2006 21:08:54]

#

Mitä tuossa koodissa tarkoittaa kohdat

kudit.push_back(Ammus(5,2,4.4,2);
kudit.push_back(Ammus(2,1,1.34,2);
kudit.push_back(Ammus(78,4,6.34,2);

Edit: Meinaako tuo sitä, että tuossa työnetään kaikki data?

Mazzimo [24.08.2006 21:47:58]

#

Siinä lisätään vektoritaulukkoon(?) nimeltä "kudit" uusia ammuksia.

Megant [24.08.2006 22:08:54]

#

Jos et osaa käyttää luokkia, suosittelen opettelemaan niiden käytön.
Ja kannattaa opetella myös STL:n juttujen käyttöä, esimerkiksi juuri nuiden vektorien käyttöä.

Heitetään nyt pari linkkiä hassun hauskasta C++-oppaasta
Oliot: http://ftp.funet.fi/index/c opas/oliot.html
Jotain STL:stä http://ftp.funet.fi/index/c opas/stl.html

Lisäksi tämä sivu toimii kätevänä kunhan osaa tarpeeksi (?) http://www.cppreference.com/

FaCo [25.08.2006 14:17:21]

#

Joo, luokat ovat ennestäänkin tuttuja mutta tuo vectroi on minulle täysin uusi...

Eli siis tuo tulisi toetuttaa SDL:ssä vaikka.

if(nappi[SDLK_SPACE]){kudit.push_back(Ammus(Pelaaja1.x,Pelaaja1.y,Pelaaja1.suunta,2);}

Löytyisikö jostain jotain listaa kaikist vectroi komennoista kuten (".size()")? Mitä tuo edes meinaa tuo ("kudit.size();");

Jos i on pienempi kuin kudit.koko i plussataan? Minkä koko? Koko = vectori luokan koko?

Blaze [25.08.2006 14:43:15]

#

FaCo kirjoitti:

Löytyisikö jostain jotain listaa kaikist vectroi komennoista kuten (".size()")?

cppreference.com on aika näpparä referenssi C:n ja C++:n standardikirjastoille.

FaCo kirjoitti:

Mitä tuo edes meinaa tuo ("kudit.size();");

kudit-olion size-metodi.

FaCo kirjoitti:

Jos i on pienempi kuin kudit.koko i plussataan? Minkä koko? Koko = vectori luokan koko?

Kuinka monta kutia siinä vektorissa on sisällä.

FaCo [25.08.2006 14:56:46]

#

Eikös for lopeta suorituksen kunnes i = kudit.size(), eikös tämän taas johda siihen että patejen liikutus/törmäyksentunnistuksen suoritus lakkaa?

sooda [25.08.2006 15:20:13]

#

Tuohan on vain esimerkki, miten niitä liikutellaan. Tollaisenaan se sitten jonnekin ohjelman päälooppiin laitettais.

FaCo [25.08.2006 15:37:05]

#

jaa niimpä tietenkin, olimpas taas tyhmä. Sitä kun ottaa tämän noobin aseman sitä sattuu kysymään todella tyhmiäkin kysymyksiä :D.

FaCo [25.08.2006 19:23:01]

#

Tarvisisin taas apua. Kun luon uuden panoksen painamalla Spacea, niin asetan ensiksi sille x = Pelaaja1.x ja Pelaaja1.y. Tämän jälkeen padille pitäisi saada täysin oma x ja y, koska muuten se ei lähtisi liikkelle vaan olisi täysin riippuvainen Pelaaja1.x ja y:tä. Eli miten tämä tulisi toteuttaa parhaiten taulukollako? Miten tämä laittaa liikutus funktioon?

Mazzimo [25.08.2006 20:12:25]

#

Siis tuota??
Jos käytät tuota Heikin tekemää Ammus-luokkaa, niin siellähän on muuttujat "x" ja "y". Tietysti konstruktorin ja muiden metodeiden toteutukset puuttuvat. Vasta ne laittavat panokset liikkeelle.

FaCo [25.08.2006 20:25:54]

#

Elikkäs Elikkäs, tarkoitatko näitä?

 private:
   float vx, vy; // Nopeusvektori
   float x,y; // Sijainti

luodaanko vai jokaiselle panokselle tuossa täysin yksityinen x ja y sekä nopeus??

Heikki [25.08.2006 20:38:48]

#

Tuo luokka ei tosiaan ole mikään lopullinen, laitoin tuon vain suuntaa-antavaksi vinkiksi.

Tarkoitin että x ja y kertovat ammuksen sijainnin (2D-)koordinaatistossa. Lisäksi vx ja vy ovat padin nopeus (eli liikutettaessa ajetaan komennot x+=vx; y+=vy;).

Tietysti jokaisella ammuksella pitää olla oma paikka ja nopeus, sillä kentällä voi olla samaan aikaan monia ammuksia liikkumassa eri suuntiin eri paikoissa.

FaCo [25.08.2006 22:29:39]

#

Siis eli..Miten tuo nyt tulisi toteutta? Eli tuo kun painetaan ampumis nappia piirretään uusi ammus ja asetetaan sen alku x ja y:ksi pelaajan x ja y tämän jälkeen ammusta alettaisiin liikuttaa...

Heikki [25.08.2006 22:52:55]

#

Lähinnä tarkoitin sellaista systeemiä, että aina kun ammutaan, luodaan uusi ammus-olio Ammus-luokasta:

if (OnPainettuAmpumisNappia()) {
  Ammus uuskuti (pelaaja.x(), pelaaja.y(), pelaaja.kulma(), PERUS_AMMUKSEN_NOPEUS);
  ammusvektori.push_back(uuskuti);
}

Kulman ja nopeuden perusteella on sitten mahdollista laskea trigonometrialla x- ja y-suuntaiset nopeudet:

vy = sin(kulma)*nopeus;
vx = cos(kulma)*nopeus;

Nyt sitten pääsilmukassa voidaan kutsua jokaisella suorituskerralla voidaan ensin liikuttaa ammuksia ja sitten piirtää ne:

for (int i=0; i < ammusvektori.size(); i++) {
  ammusvektori[i].Liikuta();
  ammusvektori[i].PiirraItsesiRuudulle();
}

Selvensikö yhtään?

Mazzimo [26.08.2006 00:29:42]

#

Tein nopsaan tälläisen kantaluokan ammuksille suurimpaan hätään. Mitään mullistavia juttuja se ei tarjoa, mutta ainakin tekee sen mitä tarvitaan: liikuttaa ja piirtää ammusta. http://koti.mbnet.fi/masa_89/koodit/ammus.h

Käyttö on hyvin yksinkertaista:

#include "SDL.h"

// sisällytetään kantaluokka ohjelmaan
#include "ammus.h"


// luodaan oma ammusluokka periyttäen se kanta::Ammuksesta
class Ammus : public kanta::Ammus
{
	public:

		// luodaan oma konstruktori
		Ammus(SDL_Surface* mS, float x, float y, float kulma)
		{
			Alusta(mS,x,y,kulma);
		}

		// voitaisiin luoda omia metodeita, mutta mitäpä tässä
		// esimerkissä turhia...
};

.............
.............

// pääkoodissa ammusta luodessa esimerkiksi:
Ammus luoti(padin_kuva, lähtö_x, lähtö_y, kulma);

......
// ja ammuksen päivitys hoituu:
luoti.Liikuta(haluttu_arvo);
luoti.Piirra(näyttö_pinta);

.............
.............

Toivottavasti auttoi edes ensi hätään.

FaCo [26.08.2006 12:25:49]

#

Mitä tämä meinaa?

"(Linker error) undefined reference to 'Ammus::Ammus(int,int,int)'"

Metabolix [26.08.2006 13:23:01]

#

Sitä, että olet käyttänyt tuollaista funktiota muttet ole kirjoittanut sen koodia minnekään (ainakaan oikeaan paikkaan, koska se ei siis ole päätynyt linkkerille asti).

FaCo [26.08.2006 13:28:15]

#

Kyllä tietääkseni olen..

class Ammus {
      public:
      Ammus(int x,int y ,int nopeus);
}

//pää koodissa
Ammus uuskuti (pelaaja.x, pelaaja.y, pelaaja.kulma,2);
  ammusvektori.push_back(uuskuti);

Megant [26.08.2006 13:36:06]

#

No, sinulla on esittely tuolle Ammus::Ammukselle, mutta sinulla ei ole sen runkoa missään.

Eli sinun pitää tehdä johonkin

Ammus::Ammus(int x, int y, int nopeus)
{
       //jotain hassua tähän konstruktoriin
}

Muista myös linkittää se mukaan.

FaCo [26.08.2006 17:13:53]

#

Joo kiitos paljon sinulle Mazzimo, mutta haluaisin eka yrittää saada "itse" tämä kehiteltyä jotenkin pystyyn ja jos en onnistui sitten käytän tuota sinun tekelettäsi.

Elikkäs..Nyt olisi sellanen problema, että miten pääsen käsiksi panosten x:ään ja y:hyn ? Tarvitsisin tätä kun teen Liikuta() funktiota.

Metabolix [26.08.2006 17:33:10]

#

Menepä lukemaan jotakin opasta, nyt ovat kyseessä sellaiset perusasiat, ettei niitä ole oikein järkeä täällä puida. Google kyllä auttaa sanoilla "C++ tutorial" tai "C++-opas".

Jäseniin pääsee käsiksi pisteen avulla, kuten lukuisissa esimerkeissä tässäkin ketjussa näkyy.

FaCo [26.08.2006 18:07:15]

#

Noh, osaan kyllä ottaa dataa ulos, mutta ei ole mitään havaintoo miten niiten dataa voi muutta jälkeen päin.

Datan ulosotto tapahtuu näin, eikö?

typedef vector<Ammus>::iterator pati_iter;
	pati_iter da = pati.begin();


		cout << *da++ ;
	}

Heikki [26.08.2006 18:14:47]

#

Öö, nyt on kyllä erittäin monimutkainen systeemi sinulla (eikä tuo edes toimi)

Jos vaikka toteutat oliolle GetX()-metodin, joka palauttaa x-koordinaatin, saat x-koordinaatin koodilla

cout << padit[numero].GetX();

FaCo [26.08.2006 18:33:53]

#

Nytten se valittaa ettei Ammus luokassa ole sen nimistä jäsentä kuin GetX,pitääkö se jotenkin määritelläkkin?

'class Ammus' has no member named 'GetX'

Megant [26.08.2006 19:17:34]

#

Tietenkin pitää määritellä, ja toteuttaa, jos haluat käyttää sitä.

Ja suosittelen tekemään kuten Metabolix sanoi, eli ota opas, ja harjoittele perusteita.

Teuvo Töhvelö [26.08.2006 19:34:34]

#

Kokeilepa vaikka tätä:
http://www.funet.fi/c opas/

Se on vissiinkin jonkin sortin klassikko ja ikävä kyllä myöskin osittain jo vanhentunut, mutta itse pidän siitä silti, sillä asiat on esitetty melko hauskasti(?) ja mielenkiintoisesti ja vieläpä suomeksi. Jonkun aikaa voi lueskellessa mennä, mutta kyllä se kannattaakin. Siitähän voi sitten jatkaa vaikkapa tuolla ylempänäkin mainituun osoitteeseen
http://www.cppreference.com

"Tyvestä puuhun!" sanoo vanha latteuskin.

FaCo [26.08.2006 22:32:33]

#

Mut en vieläkään tajua mitä hittoa teen tiedolla, että mikä on padin x??? Meinaan eikös minun pitäisi justiinsa saada syötettyä dataa x:ään, jotta voisin liikuttaa sitä???

Mazzimo [26.08.2006 22:36:23]

#

Jos käytät minun tekemää ammusluokkaa kantaluokkana, niin ei tarvitse. Ainoa ammuksen liikuttamiseen ja piirtämiseen tarvittava rivimäärä on:

kuti.Liikuta(0.5f);
kuti.Piirra(naytto_pinta);

Tietysti joudut muuttamaan muuttujanimet oikeiksi.

FaCo [26.08.2006 22:42:21]

#

hmm, noh voisinhan minä sitä käyttääkkin :P...Tosin minulla se alkaa vinnettää heti kun includetan kyseisen ammus.h:n koodiin "In file included from main.c"

Metabolix [27.08.2006 09:17:33]

#

Tämä kysely menee nyt jo aivan yli. Niin alkeellisia virheitä kuin suinkin. Et ole tainnut minkäänlaista opasta lukea eikä taida olla minkäänlaista käsitystä siitä, miten koko homma toimii. Jonkin verran pitäisi sitä perusideaa pystyä itsekin keksimään, ei ohjelmoinnista tuollaisella menolla tule yhtikäs mitään. Tässä nyt kysellään sellaisia perusasioita, jotka löytyvät jo ties kuinka monesta oppaasta ja kirjasta, eikä tässä tapauksessa ongelmana ole edes se, että ohjelmassa olisi virhe, vaan se, ettei koko ohjelmaa ole olemassakaan! Rajansa kaikella. Otapa nyt kynä ja paperia ja mieti, miten homma toimii, ja katsele sitten jostakin oppaasta, miten sellaisen saa tehtyä, tule kysymään uudestaan, kun on jokin kunnollinen ongelma edessä eikä vain yleistä en-osaa-apua-auttakaa-ongelmaa.

Viimeisessä viestissäsi on vain virheen alku, joka kertoo, missä virhe on: main.c:hen liitetyssä ammus.h:ssa.

kayttaja-3842 [28.08.2006 20:42:26]

#

Tässä tälläinen minun tekemäni yksinkertainen ammus järjestelmä...

#include <SDL/SDL.h>

using namespace std;

class Ammukset {
      public:
      int x;
      int y;
      void Piirra(SDL_Surface *kuva,SDL_Surface *naytto,int x,int y);
      };

Ammukset padit[99999];
int etu = 0;
int taka = 0;

void Ammukset::Piirra(SDL_Surface *kuva,SDL_Surface *naytto,int x,int y)
{
     SDL_Rect alue;
     alue.x = x;
     alue.y = y;
     SDL_BlitSurface(kuva,NULL,naytto,&alue);
 }

int main(int argc,char *argv[])
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL:än alustaminen epäonnistui!",SDL_GetError());
SDL_Quit();
return 0;
                            }
SDL_Surface *naytto,*patik;
naytto = SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
patik = SDL_LoadBMP("pati.bmp");
bool pois = false;
SDL_Event tapahtuma;
Uint8 *nappi;
while(pois == false)
{
SDL_PollEvent(&tapahtuma);
nappi = SDL_GetKeyState(NULL);
if(tapahtuma.type == SDL_QUIT){SDL_Quit(); return 0;}
if(nappi[SDLK_ESCAPE]){SDL_Quit(); return 0;}
if(nappi[SDLK_SPACE]){etu++;}


if(taka < etu)
{
padit[taka].x = 50;
taka++;
        }

if(taka >= etu)
{
for(int i = 0;i < etu;i++)
{
padit[i].y++;
SDL_FillRect(naytto,NULL,0);
padit[i].Piirra(patik,naytto,padit[i].x,padit[i].y);
        }

        }



SDL_Flip(naytto);
           }

SDL_FreeSurface(patik);
SDL_Quit();
return 0;
}

Megant [28.08.2006 21:39:08]

#

Ööh, tuosta on todella vaikea saada selvää, joten suosittelen että sisennät koodiasi.

FaCo [29.08.2006 11:15:11]

#

Eihän tuo edes toimi? aina kun painetaan SPACE nappia vanha pati häviää ruudusta...

kayttaja-3842 [29.08.2006 13:13:37]

#

Hoops...Taisin laittaa vanhan version, eli sen joka ei toimi :) SORI!..


Sivun alkuun

Vastaus

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

Tietoa sivustosta