SDL grafiklerinde kaydıraç uyarlaması

ArticleCategory:

SoftwareDevelopment

AuthorImage:

[Leonardo]

TranslationInfo:

original in it: Leonardo Giordani

it to en: Leonardo Giordani

en to tr: Ceyhun Elmas

AboutTheAuthor:

Milan Politecnico Telekominikasyon Mühendislik Fakültesinden diplomamı yeni aldım. Programlama ile ilgileniyorum. (çoğunlukla Assembly ve C/C++). 1999'dan beri neredeyse yalnızca Linux/Unix ile çalışıyorum.

Abstract:

Bu yazı serisi, okuyucuları "demos" olarak da bilinen çokluortam dünyası ile tanıştırmak istiyor. Bu konuyla ilgili İnternette sınırsız bilgi bulunuyor ama çok azı Linux için güzel şeyler yazıyor.Benim odaklandığım konu bazı grafik ve ses efekt teorilerini açıklamak ve bunları SDL kitaplığıyla uyarlamak. SDL ile ilgili geniş bilgileri bu adreste bulabilirsiniz :

Yazıyı anlamak için önceden bilinmesi gerekenler :

ArticleIllustration:

[sdl]

ArticleBody:

Kaydıraç (scroller)

SDL kitaplığı için Sam Lantinga'ya çok çok teşekkürler.

Kaydıraç demo'nun bir parçasıdır. Bununla ekran üzerinde kayan cümleler hazırlayabilirsiniz: bu temel efekti çoklu ortam ürünlerinde kolayca bulabilirsiniz. Bir parça haraketli yazıyı kullanıya göstermek isteyebilirsiniz. Bu yazıda sağdan sola hareket eden basit bir kaydıraçı nasıl yapacağımızı göreceğiz.

Temel fikir kaydıraçın ekranın bir parçasını bir pixel sol tarafa(ya da herhangi bir yöne) kopyalamasıdır.Bu işlemin iyi bir hızla sürekli yapılması ile istenilen sonuç elde edilir , hepsi bu.

Temel teori karmaşık değil; haydi şimdi bunu nasıl koda dökeceğimize bakalım : yğzey konusuyla işe başlayacağız. Biraz temel SDL programlama yapmış olanlarınız hemen hatırlayacaktır bunu. SDL ile çalışırken kullanıdığımız güçlü

SDL_BlitSurface() fonksiyonu herzaman hatırlanır.Bir parça SDL_Surface kopyalayalım. Bu SDL_Rect ile başka bir SDL_Surface üzerine başka bir SDL_Rect tarafından tanımlanır.

Örneğin, iki yüzey ve iki dörtgen tanımladığımızı düşünelim

#define WIDTH 800
#define HEIGHT 600

SDL_Surface *Src;
SDL_Surface *Dst;

Src = SDL_CreateRGBSurface(SDL_HWSURFACE, WIDTH, HEIGHT, 8, 
       r_mask, g_mask, b_mask, a_mask);
Dst = SDL_CreateRGBSurface(SDL_HWSURFACE, WIDTH, HEIGHT, 8, 
       r_mask, g_mask, b_mask, a_mask);

SDL_Rect BigArea = {0, 0, (WIDTH / 2), HEIGHT};
SDL_Rect SmallArea = {(WIDTH / 2) + 1, 0, (WIDTH / 2), (HEIGHT / 2)};
renk maskesini varsaydığımız yer zaten başlatılıyor. İki tam yüzeyi minimal bir çabayla kopyalatalım.
SDL_BlitSurface(Src, 0, Dst, 0);
Hedef yüzeyde dörtgenin yalnızca başlangıç koordinatlarını dikkate alıyoruz boyutu değil. Bu şu anlama geliyor:
SDL_BlitSurface(Src, &BigArea, Dst, &SmallArea);
Src 'nin sol yüzey yarısı Dst 'nin sol yüzey yarısı üzerine kopyalanıyor.

Şimdi yüzey kaldıraçı daha fazla gizlememiz gerekmiyor: yüzeyin bir parçasını aynı yüzey üzerindeki dörtgen üzerine kopyalamak yeterli. Tüm kod olmalı ama döngü içinde, bu nedenle program biraz karmaşıklaşıyor ama temel mantık oldukça basit. Döngünün her adımında iki dörtgen kullanıyoruz, ikinci basılan birincinin yolunu izliyor ve yüzeyi kendi üzerine birinci dörtgenden ikinciye kopyalıyoruz.

SDL_Surface *temp;

SDL_Rect From = {1, 0, WIDTH, HEIGHT};
SDL_Rect First = {0, 0, 1, HEIGHT};
SDL_Rect Last = {WIDTH-1, 0, 1, HEIGHT};

temp = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, HEIGHT, 8, 
       r_mask, g_mask, b_mask, a_mask);

while(1){
  SDL_BlitSurface(Src, &First, temp, 0);
  SDL_BlitSurface(Src, &From, Src, 0);
  SDL_BlitSurface(temp, &First, Src, &Last);
  SDL_BlitSurface(Src, 0, Screen, 0);
}
Gördüğünüz gibi yüzeyi sola doğru kaydırmakk yeterli değil: sağ taraftan ekrandan çıkan görüntü birimlerini yeniden içeri katmalıyız.Ya da kayan yüzey arkasında son kolonunun kopyasını bırakacak ve bir sürükleme etkisi oluşturacak. Zaten bir yüzeyin ekrana linklendiğini varsayıyoruz. Şimdi tüm programı göreceğiz. Program 480x200 pencere açıyor ve resimi sürekli kaydırıyor.
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"

#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT 200

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
static const Uint32 r_mask = 0xFF000000;
static const Uint32 g_mask = 0x00FF0000;
static const Uint32 b_mask = 0x0000FF00;
static const Uint32 a_mask = 0x000000FF;
#else
static const Uint32 r_mask = 0x000000FF;
static const Uint32 g_mask = 0x0000FF00;
static const Uint32 b_mask = 0x00FF0000;
static const Uint32 a_mask = 0xFF000000;
#endif
Bu yapılandırmalar neredeyse tüm çokluortam çalışmalarında benimsenmiş değerlerdir.
static SDL_Surface* img_surface;
static SDL_Surface* scroll_surface;
static SDL_Surface* temp_surface;
Burada kullanacağımız üç yüzey bulunuyor: img_surface dosyadan yüklenecek resmi içerir, scroll_surface yer değiştirmiş resim ve temp_surface yeniden sağ tarafa basmak zorunda olduğumuz görüntü birimleri.
static const SDL_VideoInfo* info = 0;
SDL_Surface* screen;
A SDL_VideoInfo yapısı video donanımı hakkında bilgiler içerir, screen yüzeyi gerçek ekrana noktalanırken.
int init_video()
{
  if( SDL_Init( SDL_INIT_VIDEO) < 0 )
    {
      fprintf( stderr, "Video initialization failed: %s\n",
               SDL_GetError( ) );
      return 0;
    }

  info = SDL_GetVideoInfo( );

  if( !info ) {
    fprintf( stderr, "Video query failed: %s\n",
             SDL_GetError( ) );
    return 0;
  }

  return 1;
}

int set_video( Uint16 width, Uint16 height, int bpp, int flags)
{
  if (init_video())
    {
      if((screen = SDL_SetVideoMode(width,height,bpp,flags))==0)
        {
          fprintf( stderr, "Video mode set failed: %s\n",
                   SDL_GetError( ) );
          return 0;
        }
    }
  return 1;
}
The init_video() fonksiyonu SDL Video sistemini başlatır ve info yapısını bilgilendirir. set_video() fonksiyonu video modunu yapılandırır.(boyut ve renk derinliği)
void quit( int code )
{
  SDL_FreeSurface(scroll_surface);
  SDL_FreeSurface(img_surface);

  SDL_Quit( );

  exit( code );
}
Bu olması gerekli çıkış fonksiyonudur, kullanılan tüm kaynakları serbest bırakır ve SDL_Quit olarak adlandırılır .
void handle_key_down( SDL_keysym* keysym )
{
    switch( keysym->sym )
      {
      case SDLK_ESCAPE:
        quit( 0 );
        break;
      default:
        break;
      }
}
A "key pressed" event: burada ESC tuşu anlamında.
void process_events( void )
{
    SDL_Event event;

    while( SDL_PollEvent( &event ) ) {

        switch( event.type ) {
        case SDL_KEYDOWN:
            handle_key_down( &event.key.keysym );
            break;
        case SDL_QUIT:
            quit( 0 );
            break;
        }
    }
}
Yine gerekli olan olay yönetim fonksiyonu.
void init()
{
  SDL_Surface* tmp;
  Uint16 i;

  tmp = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_WIDTH, 
       SCREEN_HEIGHT, 8, r_mask, g_mask, b_mask, a_mask);

  scroll_surface = SDL_DisplayFormat(tmp);


  SDL_FreeSurface(tmp);
Şimdi tmp ile çalışıp yüzeyi scroll_surface 'e başlatalım ve temp_surface . Her ikisi de SDL_DisplayFormat fonksiyonu sayesinde video kareyazmaç biçimine dönüştürülür.
  img_surface = IMG_Load("img.pcx");
Burada img_surface'e dosyadaki kayıtlı resimi yüklüyoruz.
  for (i = 0; i < SDL_NUMEVENTS; ++i)
    {
      if (i != SDL_KEYDOWN && i != SDL_QUIT)
        {
          SDL_EventState(i, SDL_IGNORE);
        }
    }

  SDL_ShowCursor(SDL_DISABLE);
}
Tüm olaylar programdan çıkış için tuşa basmanın dışında görmezlikten geliniyor ; dahası kursoru tanımsız hale getiriyoruz.
int main( int argc, char* argv[] )
{
  SDL_Rect ScrollFrom = {1, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
  SDL_Rect First = {0, 0, 1, SCREEN_HEIGHT};
  SDL_Rect Last = {SCREEN_WIDTH - 1, 0, 1, SCREEN_HEIGHT};
Burada yazıda açıklanan üç dörtgen bulunuyor.
  if (!set_video(SCREEN_WIDTH, SCREEN_HEIGHT, 8, 
      SDL_HWSURFACE | SDL_HWACCEL | SDL_HWPALETTE /*| SDL_FULLSCREEN*/))
   quit(1);

  SDL_WM_SetCaption("Demo", "");

  init();

  SDL_BlitSurface(img_surface, 0, scroll_surface, 0);
Bu kod herşeyi başlatıyor: video modunun kurulması, pencerlerin yazılması, çağrılar init() Bu kod herşeyi başlatıyor: video modunun kurulması, pencerlerin yazılması, çağrılar ... Ve scroll_surface hazırlıyor.
  while( 1 )
    {
      process_events();

      SDL_BlitSurface(scroll_surface, &First, temp_surface, 0);

      SDL_BlitSurface(scroll_surface, &ScrollFrom, scroll_surface, 0);

      SDL_BlitSurface(temp_surface, &First, scroll_surface, &Last);

      SDL_BlitSurface(scroll_surface, 0, screen, 0);

      SDL_Flip(screen);
    }

  return 0;
}
Bu da yazıda açıklanan döngü: yalnızca olay denetim fonksiyonu ve yüzey eklendi.

Görüldüğü gibi kitaplık açısından çalışmanın başlatılması kısa değil, ama avantajı tüm demoyu içermesi, kod artarken bile başlatma tüm programın küçük ve kullanışlı bir parçası olacak.

A demo

Burada kaydıraçın farklı anlardaki görünümleri bulunuyor:
state1 state2

ps: Yorumlarınızı, önerilerinizi za da sorularınızı İngilizce, Almanca ya da İtalyanca olarak ileti adresimden ya da Talkback sayfasından bana gönderebilirsiniz.