Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Pinnat pyörimään (rotation)

Sivun loppuun

Moppi [23.06.2005 12:13:30]

#

Voiko c++:ssa saada eri pintoja pyörähtämään ympäri, niinkuin joissain kuvankäsittely-ohjelmissa, vaikkapa 90-astetta.
Jos voi niin miten?

Metabolix [23.06.2005 12:45:58]

#

Jonkinlainen tarkennus olisi paikallaan. Vaikkapa ihan siirtämällä pikselit (x,y) kohtaan (korkeus-y,x). OpenGL:n pinnat pyörivät glRotatef-funktiolla. SDL:ssä SLD_gfx-kirjaston rotozoomSurface.

Moppi [25.06.2005 15:10:57]

#

Nyt löysin mitä etsinkin kiitos avusta.

Moppi [26.06.2005 12:56:56]

#

Kun käytän SDL_gfx kirjaston rotozoomSurface:a kuva lähtee vierimään oikeaan alaviistoon. Luulen että tämä johtuu jotenkin siitä että x- ja y-koordinaatit eivät saa tiettyä arvoa jonka voisin lisätä pyörimis kohtaan

Koodini:

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL_rotozoom.h>

SDL_Surface *back;
SDL_Surface *image;
SDL_Surface *screen;

int xpos=0,ypos=0;

int InitImages()
{
  back = SDL_LoadBMP("c:\\...\\...\\bg.bmp");
  image = SDL_LoadBMP("c:\\...\\...\\image.bmp");
  return 0;
}

void DrawIMG(SDL_Surface *img, int x, int y)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}

void DrawIMG(SDL_Surface *img, int x, int y, int w, int h, int x2, int y2)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_Rect dest2;
  dest2.x = x2;
  dest2.y = y2;
  dest2.w = w;
  dest2.h = h;
  SDL_BlitSurface(img, &dest2, screen, &dest);
}

void DrawBG()
{
  DrawIMG(back, 0, 0);
}

void DrawScene()
{
  DrawIMG(back, xpos-2, ypos-2, 132, 132, xpos-2, ypos-2);
  DrawIMG(image, xpos, ypos);

  SDL_Flip(screen);
}

void rotation(){
		static double rotationAngle = 0;
		rotationAngle += 0.3;
		image = rotozoomSurface(image, rotationAngle, 1, 0);
		DrawScene();}


int main(int argc, char *argv[])
{
  Uint8* keys;

  if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 )
  {
    printf("Unable to init SDL: %s\n", SDL_GetError());
    exit(1);
  }
  atexit(SDL_Quit);

  screen=SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
  if ( screen == NULL )
  {
    printf("Unable to set 640x480 video: %s\n", SDL_GetError());
    exit(1);
  }

  InitImages();
  DrawBG();

  int done=0;

  while(done == 0)
  {
    SDL_Event event;

    while ( SDL_PollEvent(&event) )
    {
      if ( event.type == SDL_QUIT )  {  done = 1;  }

      if ( event.type == SDL_KEYDOWN )
      {
        if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
      }
    }
    keys = SDL_GetKeyState(NULL);
    if ( keys[SDLK_UP] ) { ypos -= 1; }
    if ( keys[SDLK_DOWN] ) { ypos += 1; }
    if ( keys[SDLK_LEFT] ) { xpos -= 1; }
    if ( keys[SDLK_RIGHT] ) { xpos += 1; }
    if ( keys[SDLK_SPACE] ) { rotation(); }
    DrawScene();
  }

  return 0;
}

Mikä avuksi?

Gaxx [26.06.2005 14:25:28]

#

Nämä kaksi funktiota kaipaisivat vähän muokkausta:

void DrawScene()
{
  DrawIMG(back, xpos-2, ypos-2, 132, 132, xpos-2, ypos-2);
  DrawIMG(image, xpos, ypos);

  SDL_Flip(screen);
}

void rotation(){
        static double rotationAngle = 0;
        rotationAngle += 0.3;
        image = rotozoomSurface(image, rotationAngle, 1, 0);
        DrawScene();}

Muotoon:

void DrawScene()
{
  DrawIMG(back, xpos-2, ypos-2, 132, 132, xpos-2, ypos-2);
  DrawIMG(image2, xpos-image2->w/2, ypos-image2->h/2);

  SDL_Flip(screen);
}

void rotation(){
        static double rotationAngle = 0;
        rotationAngle += 1;
        image2 = rotozoomSurface(image, rotationAngle, 1, 0);
        DrawScene();}

Käännä kuva aina alkuperäisestä kuvasta, niin saat huomattavasti parempaa jälkeä ja kuva ei lähde vierimään miten sattuu. Ja jotta se kummallinen heiluminen sen pyörimisen aikana lähtisi pois niin pitäisi muuttaa rivi

DrawIMG(image, xpos, ypos);

Muotoon:

DrawIMG(image2, xpos-image2->w/2, ypos-image2->h/2);

Ongelmana on se, että ainakin itselläni SDL suorittaa virheellisen toiminnan jälkimmäisen rivin kanssa ja ohjelma sammuu mitään ilmoittelematta.

Niin ja sitten image2 pitää määritelläkin!

Moppi [27.06.2005 14:10:01]

#

Mitä nämä xpos-image2->w/2 ja ypos-image2->h/2 oikein meinaavat?????????

Metabolix [27.06.2005 15:07:25]

#

Siis halutusta x-sijainnista vähennetään kuva->w / 2 ja y-sijainnista kuva->h / 2, jolloin haluttuun kohtaan (x,y) saadaan kuvan keskikohta. Tuolla tavalla keskikohta on kohdallaan vielä pyörityksen jälkeenkin.

Kannattaa varmaankin kääntää uuden pinnan tilalle aina se alkuperäinen, ettei pinta vain kasva kasvamistaan (vai mitä SDL:n tuntijat sanovat?) Käännettäessähän kulmiin lisätään tyhjää tilaa, koska pinta on aina vaakasuora suorakulmio.

Gaxx [27.06.2005 15:50:21]

#

Metabolix kirjoitti:

Kannattaa varmaankin kääntää uuden pinnan tilalle aina se alkuperäinen, ettei pinta vain kasva kasvamistaan (vai mitä SDL:n tuntijat sanovat?) Käännettäessähän kulmiin lisätään tyhjää tilaa, koska pinta on aina vaakasuora suorakulmio.

Se on laitettu tuohon korjattuun koodiin, mutta en ole sitä näemmä sen pahemmin selittänyt :)

Elikkäs:

image = rotozoomSurface(image, rotationAngle, 1, 0);

->

image2 = rotozoomSurface(image, rotationAngle, 1, 0);

Metabolix [27.06.2005 16:30:08]

#

Joo, en vilkaissutkaan koodiasi, vaan totesin ihan vain kysyjälle vihjeeksi. Sitähän olisi vain helppo laittaa joka frameen käännös:

if (keys[SDLK_RIGHT])
  kuva = rotozoomSurface(kuva, 1.0f, 1, 0);

Lopputuloksena pelin loppuvaiheissa 1000000 x 1000000 -surface, jossa on enimmäkseen tyhjää, ja kuvan tunnistettavuus olisi myös kärsinyt samassa mittakaavassa, eli harmahtava laikku keskellä surfacea :)

Moppi [30.06.2005 20:37:44]

#

Nyt onnistuu, mutta kysyisin vielä että mitenkäs onnistuisi monen eri pinnan liittäminen toisiinsa.

Jos olisin esimerkiksi piirtänyt bittikartoille kolmion, ympyrän, neliön ja jonkinlaisen taustan, jonka jälkeen liitän ne ERI pinnoille. Nyt haluisin liittää pinnat toistensa päälle,mutta eri pintojen reunat jäävät näkyviin (pinnat ovat sorakulmaisia).

SDL_SetColorKey(*img, SDL_SRCCOLORKEY, SDL_MapRGB(*img->format, r, b, g))

Tämän avulla saan taustan näkyviin pintojen välistä, mutta haluankin kyseistä pintaa "alemman" pinnan näkyviin.
Miten tämä onnistuu???

Olen aikaisemmin antamaani koodia muuttamalla yrittänyt saada tälläistä aikaan, mutta en ole onnistunut.

Metabolix [30.06.2005 21:11:53]

#

Asetat colorkeyt ja piirrät järjestyksessä.

void DrawScene()
{
  DrawIMG(back, ...);
  DrawIMG(kolmio, ...);
  DrawIMG(nelio, ...);
  DrawIMG(ympyra, ...);

  SDL_Flip(screen);
}

Lopputuloksena pohjalla on tausta, sen pälle on piirretty kolmio, sitten neliö ja lopuksi ympyrä.
Vai enkö nyt ymmärtänyt alkuunkaan?


Sivun alkuun

Vastaus

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

Tietoa sivustosta