یک نکته!

واسه وبلاگرها :‌ از Internet Explorer  برای update استفاده کنید چون بلاگ اسکای فقط IE را کامل ساپورت می کنه

واسه بینندها! : ! JUST FIREFOX بخاطر این که صفحه ها سنگینند و FireFox ذره ذره لود می کنه

 

فقط همین...!

درس 7 :True Type Font (TTF)

درس 7 :True Type Font (TTF)

SDL_ttf یک کتاب خانه الحاقی است که به وسیله ان می توانیم سطوحی از فونتهای TTF بسازیم

شما می توانید SDL_ttf را از اینجا دانلود کنید here

طبق درس 3 شما می توانید SDL_ttf را نصب کنید

 

//The surfaces

SDL_Surface *background = NULL;

SDL_Surface *message = NULL;

SDL_Surface *screen = NULL;

 

//The event structure

SDL_Event event;

 

//The font that's going to be used

TTF_Font *font;

 

//The color of the font

SDL_Color textColor = { 255, 255, 255 };

 

در اینجا ما متغییر ها را تعریف می کنیم backgroung . screen والبته message که مسئول نگهداری متن ما است

در اینجا دو نوع ساختار جدید می بینید SDL_Color که ساختاری برای نگهداری رنگ است و TTF_Font فونت است که ما می خواهیم استفاده کنیم

bool init()

{

    //Initialize all SDL subsystems

    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )

    {

        return false;   

    }

   

    //Set up the screen

    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

   

    //If there was in error in setting up the screen

    if( screen == NULL )

    {

        return false;   

    }

   

    //Initialize SDL_ttf

    if( TTF_Init() == -1 )

    {

        return false;   

    }

   

    //Set the window caption

    SDL_WM_SetCaption( "TTF Test", NULL );

   

    //If everything initialized fine

    return true;

}

این تابع هم خیلی شبیه تابع قبلی است با فرق این که TTF_Init در آن کار اماده کردن محیط TTF را بر عهده دارد قبل از کار کردن با هر تابع TTF باید این دستور نوشته شود

bool load_files()

{

    //Load the background image

    background = load_image( "background.png" );

   

    //Open the font

    font = TTF_OpenFont( "artro.ttf", 28 );

   

    //If there was a problem in loading the background

    if( background == NULL )

    {

        return false;   

    }

   

    //If there was an error in loading the font

    if( font == NULL )

    {

        return false;

    }

   

    //If everything loaded fine

    return true;   

}

این تابع بارگزاری فایل هاست قبل از استفاده از هر TTF باید بوسیله  TTF_OpenFont اماده شود

اولین پارامتر مسیر و اسم فونت است دومین پارامتر سایز نوشته است در صورت بروز خطا مقدار NULL را بر می گرداند

    //Render the text

    message = TTF_RenderText_Solid( font, "The quick brown fox jumps over the lazy hound", textColor );

   

    //If there was an error in rendering the text

    if( message == NULL )

    {

        return 1;   

    }

   

    //Apply the images to the screen

    apply_surface( 0, 0, background, screen );

    apply_surface( 0, 200, message, screen );

   

    //Update the screen

    if( SDL_Flip( screen ) == -1 )

    {

        return 1;   

    }

سریعترین را برای نمایش فونت استفاده از تابع TTF_RenderText_Solid است که بی کیفیت ترین هم هست 3 پارامتر می گیرد فونت . متن و رنگ راههای دیگر هم هست که در Document TTF موجود است

void clean_up()

{

    //Free the surfaces

    SDL_FreeSurface( background );

    SDL_FreeSurface( message );

   

    //Close the font that was used

    TTF_CloseFont( font );

   

    //Quit SDL_ttf

    TTF_Quit();

   

    //Quit SDL

    SDL_Quit();

}

این تابع هم کار تمیز کردن حافظه را انجام می دهد

 

مباحث تکمیلی :

تابع دیگری به نام

SDL_Surface *TTF_RenderText_Blended(TTF_Font *font, const char *text, SDL_Color fg)

که کیفیت فوق العاده ای دارد

تابع دیگری به نام :

SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg)

که 4 پارامتر  می گیرد که یکی هم رنگ پس زمینه است و یک کادر دور ان می کشد

 

تابع دیگری به نام

void TTF_SetFontStyle(TTF_Font *font, int style)

که کار زیر خط دار کردن و توپر کردن و زیر خط دار کردن فونت را تعیین می کند

 

TTF_STYLE_BOLD
TTF_STYLE_ITALIC
TTF_STYLE_UNDERLINE

Example :

TTF_SetFontStyle(font, TTF_STYLE_BOLD|TTF_STYLE_ITALIC);

 

توضیح

در صورت مواجه شدن با مشکل یا کم توضیح دادن من در جایی یا اشتباه نوشتن من خواشمندم که به من اطاع دهید

درس ۶ : استفاده از Sprite ها

فایلهای استفاده شده :

source code

pic

 

استفاده از Sprite ها  :

Sprite در حقیقت یک فایل عکس است که در ان چندین عکس موجود است مثلا در یک بازی ساده که از 25 عکس استفاده می شود 2 راه وجود دارد یکی این که 25 فایل مجزا داشته باشیم و دیگر این که 1 فایل بزرگ شامل همه این 25 عکس راه حل دوم بهتر است

//The surfaces

SDL_Surface *dots = NULL;

SDL_Surface *screen = NULL;

 

//The event structure

SDL_Event event;

 

//The portions of the sprite map to be blitted

SDL_Rect clip[ 4 ];

 

در اینجا ما چند متغییر global تعریف کردیم سطوح ساختار event و یک ارایه از SDL_Rect که مختصات 4 عکس را در بر دارد

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )

{

    //Holds offsets

    SDL_Rect offset;

   

    //Get offsets

    offset.x = x;

    offset.y = y;

   

    //Blit

    SDL_BlitSurface( source, clip, destination, &offset );

}

این تابع apply_surface ما است اما با کمی دستکاری پارامتر جدید clip است از نوع اشاره گر به SDL_Rect که مختصات مر بعی از ان عکس  است که ما می خواهیم  بچسبانیم اگر NULL بفرستیم دیگر فرقی با تابع قبلی نخواهد داشت  و تغییر دوم عوض کردن پارامتر دوم SDL_BlitSurface از NULL به clip است

    //Clip range for the top left

    clip[ 0 ].x = 0;

    clip[ 0 ].y = 0;

    clip[ 0 ].w = 100;

    clip[ 0 ].h = 100;

   

    //Clip range for the top right

    clip[ 1 ].x = 100;

    clip[ 1 ].y = 0;

    clip[ 1 ].w = 100;

    clip[ 1 ].h = 100;

   

    //Clip range for the bottom left

    clip[ 2 ].x = 0;

    clip[ 2 ].y = 100;

    clip[ 2 ].w = 100;

    clip[ 2 ].h = 100;

   

    //Clip range for the bottom right

    clip[ 3 ].x = 100;

    clip[ 3 ].y = 100;

    clip[ 3 ].w = 100;

    clip[ 3 ].h = 100;

در تابع main بعد از اماده شدن و بارگزاری فایلها ما مختصات 4 عکس را تنظیم می کنیم

در ادامه کار

    //Fill the screen white

    SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );

 

ما از تابع SDL_FillRect استفاده می کنیم که یک سطح رامی گیرد و ناحیه مشخص شده از سطح که پارامتر دوم است د باید از جنس SDL_Rect باشد را به رنگ پارامتر سوم در می اورد

    //Apply the images to the screen

    apply_surface( 0, 0, dots, screen, &clip[ 0 ] );

    apply_surface( 540, 0, dots, screen, &clip[ 1 ] );

    apply_surface( 0, 380, dots, screen, &clip[ 2 ] );

    apply_surface( 540, 380, dots, screen, &clip[ 3 ] );

   

    //Update the screen

    if( SDL_Flip( screen ) == -1 )

    {

        return 1;   

    }

حالا کار ما به اتمام رسیده است و نتیجه پایانی به صورت زیر است

درس 5: Color Keying

فایل های استفاده شده :

source code

adamak

‌background

درس 5: Color Keying (حذف کردن رنگهای مشخص در هنگام چسباندن)

 

ساختار SDL_Surface دارای عضوی به نام color key است

Color key رنگ مشخصی است که ما در هنگام چسباندن نمی خواهیم حضور یابد

 فرض کنید می خواهید این ادمک را به

این پس زمینه بچسبانید

ولی شما نمی خواهید اون رنگ ابی کم رنگ مزاحمتان شود

برای اینکار شما می توانید این رنگ ابی را به عنوان color key معرفی کنید

 

یک مقدمه در مورد رنگها :

همه رنگها از سه رنگ اصلی قرمزوسبزو آبی تشکیل شده اند (Red Green Blue)[RGB]  

هر رنگ از یک بایت تشکیل شده است پس جمعا 256*256*256 رنگ با این مدل می توان ساخت

یعنی : 16777216 رنگ می توان با این مدل ساخت.

مثلا رنگ 0 , 0 , 0 معرف رنگ سیاه است یعنی هیچ رنگی از هیچ کدام موجود نیست

یا رنگ 255,0,0 معرف قرمز مطلق

یا رنگ 0,255,0 معرف سبز مطلق

یا رنگ 0,0,255 معرف ابی مطلق

یا رنگ 255,255,255 معرف سفید

و رنگ 0,255,255 معرف همین ابی کم رنگ است

شما در مبنای HEX یعنی مبنی 16 هم می توانید بنویسید اعداد پایه HEX شامل :

1 2 3 4 5 6 7 8 9 A B C D E F

هست (ماشین حساب ویندوز یا لینوکس را ببینبد)

این رنگ ابی 0,0,FF است

 

معمولا color key را در هنگام بارگزاری فایل ست می کنند

SDL_Surface *load_image( std::string filename )

{

    //The image that's loaded

    SDL_Surface* loadedImage = NULL;

   

    //The optimized image that will be used

    SDL_Surface* optimizedImage = NULL;

   

    //Load the image

    loadedImage = IMG_Load( filename.c_str() );

   

    //If the image loaded

    if( loadedImage != NULL )

    {

        //Create an optimized image

        optimizedImage = SDL_DisplayFormat( loadedImage );

       

        //Free the old image

        SDL_FreeSurface( loadedImage );

این همان تابع image_load است که ما می خواهیم تغییر دهیم

        //If the image was optimized just fine

        if( optimizedImage != NULL )

        {

            //Map the color key

            Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );

حالا هر می خواهیم color key را مشخص کنیم

تابع SDL_MapRGB 4 پارامتر می گیرد و رنگ مورد نظر را بر می گرداند پارامتر اول فرمت رنگ مثلا 32 bit که ما اینجا از فرمت optimizedImage استفاده می کنیم و سپس سه رنگ را می دهیم

            //Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent

            SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey );

        }

حالا وقت انجام Color keying  است SDL_SetColorKey سه پارامتر می گیرد سطح مورد نظر . تنظیمات و رنگ

    //Return the optimized image

    return optimizedImage;

}

سر اخر optimizeImage  دستکاری شده را به ما می دهد

    //Apply the surfaces to the screen

    apply_surface( 0, 0, background, screen );

    apply_surface( 240, 190, foo, screen );

   

    //Update the screen

    if( SDL_Flip( screen ) == -1 )

    {

        return 1;   

    }

حال شکل مورد نظر به صورت زیر است

درس 4 : برنامه های مبتنی بر رویداد ( حادثه )

فایلهای استفاده شده :

source code

عکس

 

 

درس 4 : برنامه های مبتنی بر رویداد ( حادثه )

 

یک رویداد اتفاقی است که رخ می دهد مثل فشار دادن دکمه p صفحه کلید تکان دادن Mouse تغییر اندازه پنجره برنامه  کلیک کردن بر روی دکمه X یا ضربدر پنجره و ...

 

در این درس یاد می گیرید که چگونه رخداد یک رزیداد را بررسی کنید و مثال ما همان زدن X است

 

//The headers

#include "SDL/SDL.h"

#include "SDL/SDL_image.h"

#include

 

//Screen attributes

const int SCREEN_WIDTH = 640;

const int SCREEN_HEIGHT = 480;

const int SCREEN_BPP = 32;

 

//The surfaces

SDL_Surface *image = NULL;

SDL_Surface *screen = NULL;

 

در اول کار مثل قبل هدر و ثابت ها و سطوح را تعریف می کنیم

//The event structure that will be used

SDL_Event event;

حال یک چیز جدید ساختار SDL_Event به ما در نگهداری رویداد ها کمک می کند در اصل SDL_Event یک union است به شکل زیر :

 

typedef union{
  Uint8 type;
  SDL_ActiveEvent active;
  SDL_KeyboardEvent key;
  SDL_MouseMotionEvent motion;
  SDL_MouseButtonEvent button;
  SDL_JoyAxisEvent jaxis;
  SDL_JoyBallEvent jball;
  SDL_JoyHatEvent jhat;
  SDL_JoyButtonEvent jbutton;
  SDL_ResizeEvent resize;
  SDL_ExposeEvent expose;
  SDL_QuitEvent quit;
  SDL_UserEvent user;
  SDL_SywWMEvent syswm;
} SDL_Event;
 

 

SDL_Surface *load_image( std::string filename )

{

    //The image that's loaded

    SDL_Surface* loadedImage = NULL;

   

    //The optimized image that will be used

    SDL_Surface* optimizedImage = NULL;

   

    //Load the image

    loadedImage = IMG_Load( filename.c_str() );

   

    //If the image loaded

    if( loadedImage != NULL )

    {

        //Create an optimized image

        optimizedImage = SDL_DisplayFormat( loadedImage );

       

        //Free the old image

        SDL_FreeSurface( loadedImage );

    }

   

    //Return the optimized image

    return optimizedImage;

}

 

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )

{

    //Temporary rectangle to hold the offsets

    SDL_Rect offset;

   

    //Get the offsets

    offset.x = x;

    offset.y = y;

   

    //Blit the surface

    SDL_BlitSurface( source, NULL, destination, &offset );

}

این توابع همچنان مثل درس های قبل است و تغییر نکرده اند

bool init()

{

    //Initialize all SDL subsystems

    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )

    {

        return false;   

    }

   

    //Set up the screen

    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

   

    //If there was in error in setting up the screen

    if( screen == NULL )

    {

        return false;   

    }

   

    //Set the window caption

    SDL_WM_SetCaption( "Event test", NULL );

   

    //If everything initialized fine

    return true;

}

این تابع هم برای اماده سازی است تغییر تیتر شروع SDL و چک کردن برای Error .

bool load_files()

{

    //Load the image

    image = load_image( "x.png" );

   

    //If there was an error in loading the image

    if( image == NULL )

    {

        return false;   

    }

   

    //If everything loaded fine

    return true;   

}

 

این تابع برای بارگزاری فایل است و چک کردن برای بروز خطا توجه کنید که فایل x.png حتما باید باشد.

void clean_up()

{

    //Free the image

    SDL_FreeSurface( image );

   

    //Quit SDL

    SDL_Quit();   

}

واین تابع اخر هم کار خالی کردن حافظه و خروج از SDL را انجام می دهد

int main( int argc, char* args[] )

{

    //Make sure the program waits for a quit

    bool quit = false;

در تابع main ما یک متغییر تعریف کردیم به نام quit که در صورت TRUE شدن از برنامه خارج شود

//Initialize

if( init() == false )

{

     return 1;   

}

 

 //Load the files

if( load_files() == false )

{

return 1;   

}

 

در اینجا توابع را فراخوانی می کنیم

    //Apply the surface to the screen

    apply_surface( 0, 0, image, screen );

   

    //Update the screen

    if( SDL_Flip( screen ) == -1 )

    {

        return 1;   

    }

سپس عکس را نمایش می دهیم

    //While the user hasn't quit

    while( quit == false )

    {

این حلقه اصلی برنامه است تا وقتی که برنامه مقدار quit را true نکرده باشد ادامه میابد.

        //While there's an event to handle

        while( SDL_PollEvent( &event ) )

        {

 

در SDL همانند Windows وقتی چند رویداد دخ میدهد این رویداد ها درون یک صف قرار می گیرند و هر کی اول تو صف ایستاد اول هم پردازش می شود حال ما چطور می توانیم این ها را از تو صف در اوریم ؟

جواب : استفاده از تابع SDL_PollEvent() است و یک ساختار SDL_Event

 

ما یک ساختار را به صورت ارجاع به SDL_PollEvent  می فرستیم واین تابع هم ان را دستکاری می کند

و تا موقعی که کسی درون صف باشد SDL_PollEvent مقدار غیر صفر بر میگرداند

            //If the user has Xed out the window

            if( event.type == SDL_QUIT )

            {

                //Quit the program

                quit = true;

            }   

        }

    }

وقتی کاربر دکمه X را بزند از حلقه بیرون می اید

 

    //Free the surface and quit SDL

    clean_up();

       

    return 0;   

}

در اینجا هم برنامه پایان میابد

 

بحث تکمیلی :

SDL_Event را می توان بعد از SDL_Surface مهمترین ساختار SDL دانست.

این ها مثال هایی از type هستند

Event type        Event Structure

SDL_ACTIVEEVENT            SDL_ActiveEvent

SDL_KEYDOWN/UP            SDL_KeyboardEvent

SDL_MOUSEMOTION         SDL_MouseMotionEvent

SDL_MOUSEBUTTONDOWN/UP   SDL_MouseButtonEvent

SDL_JOYAXISMOTION       SDL_JoyAxisEvent

SDL_JOYBALLMOTION      SDL_JoyBallEvent

SDL_JOYHATMOTION        SDL_JoyHatEvent

SDL_JOYBUTTONDOWN/UP         SDL_JoyButtonEvent

SDL_QUIT      SDL_QuitEvent

SDL_SYSWMEVENT            SDL_SysWMEvent

SDL_VIDEORESIZE  SDL_ResizeEvent

SDL_VIDEOEXPOSE            SDL_ExposeEvent

SDL_USEREVENT     SDL_UserEvent

 

SDL_Event دو استفاده دارد

1.خواندن رویداد ها از صف (به وسیله SDL_PollEvent)

2.قرار دادن رویدادهای مصنوعی در صف(به وسیله SDL_PushEvent)

مثال :

SDL_Event test_event;
while(SDL_PollEvent(&test_event)) {
  switch(test_event.type) {
    case SDL_MOUSEMOTION:
      printf("We got a motion event.
");
      printf("Current mouse position is: (%d, %d)
", test_event.motion.x, test_event.motion.y);
      break;
    default:
      printf("Unhandled Event!
");
      break;
  }
}
printf("Event queue empty.
");

 

 

در درسهای بعدی در مورد برنامه نویسی Mouse به شما خواهم گفت تا چند درس دیگر.