Введение в Simple DirectMedia Layer

Версия для печати

Архив документации на OpenNet.ru / Раздел "Программирование, языки" (Многостраничная версия)

Введение в Simple DirectMedia Layer

Перевод на русский язык: Скиданов Александр (mailto:shd@bk.ru), Сашнов Александр (mailto:sashnov@ngs.ru)
Оригинал перевода.

Содержание:

  1. О разработчике и переводчиках
  2. Simple DirectMedia Layer
    1. Что это такое?
      • SDL - бесплатный кросс платформенный мультимедийный API для разработчиков
      • Использование для игр
      • Использование для игровых SDK
      • Использование для эмуляторов
      • Использование для демонстраций
      • Использование для мультимедиа-приложений
    2. Что она может делать?
      • Видео
      • События
      • Звук
      • CD-ROM аудио
      • Потоки
      • Таймеры
      • Независимость от порядка байтов ( e ndian independence)
    3. На каких платформах выполняется?
      • Linux
      • Win32
      • BeOS
      • Неофициально перенесены, в процессе переноса
  3. Использование Simple DirectMedia Layer API
    1. Инициализация библиотеки
    2. Видео
      • Выбор и установка разрешения и глубины цвета (простой способ)
      • Рисование точек (pixels) на экране
      • Загрузка и отображение рисунков
    3. События
      • Ожидание событий
      • Опрос событий
      • Опрос состояния события
    4. Звук
      • Открытие аудио устройства
      • Загрузка и воспроизведение звука
    5. CD-ROM аудио
      • Открытие CD-Rom привода для последующего использования
      • Проигрывание CD-Rom'а
    6. Потоки
      • Создание простого потока
      • Синхронизация доступа к ресурсам
    7. Таймеры
      • Получение текущего времени в миллисекундах
      • Ожидание указанного количества миллисекунд
    8. Порядок байтов (endian independence)
      • Определение порядка байтов в текущей системе
      • Обмен данными между системами с различным порядком байтов

[ Дальше ]


[Назад] Содержание ] [Далее]

О разработчике:

Sam Lantinga, Инженер по программному обеспечению в Blizzard Entertainment.

Фоновая деятельность:

Связь:

 

Перевод на русский язык :

 

Скиданов Александр
mailto:shd@bk.ru
http://morgeyz.narod.ru/

 

Сашнов Александр
mailto:sashnov@ngs.ru
http://sashnov.chat.ru/

 

 

[Назад] Содержание ] [Далее]


Введение в Simple DirectMedia Layer

Перевод на русский язык: Скиданов Александр (mailto:shd@bk.ru), Сашнов Александр (mailto:sashnov@ngs.ru)
Оригинал перевода.

Содержание:

  1. О разработчике и переводчиках
  2. Simple DirectMedia Layer
    1. Что это такое?
      • SDL - бесплатный кросс платформенный мультимедийный API для разработчиков
      • Использование для игр
      • Использование для игровых SDK
      • Использование для эмуляторов
      • Использование для демонстраций
      • Использование для мультимедиа-приложений
    2. Что она может делать?
      • Видео
      • События
      • Звук
      • CD-ROM аудио
      • Потоки
      • Таймеры
      • Независимость от порядка байтов ( e ndian independence)
    3. На каких платформах выполняется?
      • Linux
      • Win32
      • BeOS
      • Неофициально перенесены, в процессе переноса
  3. Использование Simple DirectMedia Layer API
    1. Инициализация библиотеки
    2. Видео
      • Выбор и установка разрешения и глубины цвета (простой способ)
      • Рисование точек (pixels) на экране
      • Загрузка и отображение рисунков
    3. События
      • Ожидание событий
      • Опрос событий
      • Опрос состояния события
    4. Звук
      • Открытие аудио устройства
      • Загрузка и воспроизведение звука
    5. CD-ROM аудио
      • Открытие CD-Rom привода для последующего использования
      • Проигрывание CD-Rom'а
    6. Потоки
      • Создание простого потока
      • Синхронизация доступа к ресурсам
    7. Таймеры
      • Получение текущего времени в миллисекундах
      • Ожидание указанного количества миллисекунд
    8. Порядок байтов (endian independence)
      • Определение порядка байтов в текущей системе
      • Обмен данными между системами с различным порядком байтов

[ Дальше ]


[ Назад ] Содержание [ Дальше ]

Использование Simple DirectMedia Layer API

Использование CD-ROM audio 

  • Открытие CD-ROM устройства для последующего использования 

Во можете узнать количество CD-Rom устройств в системе вызвав функцию SDL_CDNumDrives() и затем открыть один из них, вызвав SDL_CDOpen(). 

Основной (по умолчанию) CD-ROM всегда 0. Заметьте, что CD-ROM устройство может быть открыто, даже если в дисковод не вставлен диск. 

Для определения текущего состояния устройства вы можете воспользоваться функцией SDL_CDStatus(). По завершении использования CD-ROM устройства, закройте его функцией SDL_CDClose(). 

Совет:
Вы можете определить системное имя CD-ROM дисковода используя SDL_CDName() функцию. 

 

Пример

{


    SDL_CD *cdrom;



 

    
if
 ( SDL_CDNumDrives() > 0 ) {


        cdrom = SDL_CDOpen(0);


        
if
 ( cdrom == NULL ) {


            fprintf(stderr, "Не могу открыть CD-ROM по умолчанию: %s\n" SDL_GetError());


            return;
        }
 
        ...
 
        SDL_CDClose(cdrom);
    }
}

 

  • Воспроизведение CD-ROM дисков 

CD-ROM диски используют время в MSF формате (mins/secs/frames = минуты/секунды/кадры) или непосредственно в кадрах. Кард - это стандартная единица времени для CD, равная 1/75 секунды. SDL использует кадры вместо MFS формата когда определяет длину трека и текущее положение, но вы всегда можете конвертировать один формат в другой с помощью макросов FRAMES_TO_MSF() и MSF_TO_FRAMES(). 

SDL не обновляет автоматически информацию с структуре SDL_CD пока вы не вызовете SDL_CDStatus(), таким образом вы должны вызывать SDL_CDStatus каждый раз, когда вам надо узнать, что за диск вставлен в дисковод и какие треки на нем доступны. Заметьте, что первый трек имеет индекс 0. 

SDL имеет две функции для воспроизведения CD-ROM. Вы можете как играть определенный трек, используя функцию SDL_CDPlayTracks(), так и устанавливать смещение от начала всего диска, используя SDL_CDPlay(). 

SDL не предусматривает автоматическое оповещение при вставке CD или при завершении воспроизведения. Для отслеживания этих ситуаций вы должны периодически производить опрос состояния устройства с помощью SDL_CDStatus().

Совет:
Чтобы понять, какие треки - аудио треки, а какие - треки данных, вы можете прочитать cdrom->tracks[track].type, и сравнить с SDL_AUDIO_TRACK и SDL_DATA_TRACK. 

 

Пример

void
 PlayTrack(SDL_CD *cdrom, 
int
 track)


{


    
if
 ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) {


        SDL_CDPlayTracks(cdrom, track, 0, track+1, 0);


    }


    
while
 ( SDL_CDStatus(cdrom) == CD_PLAYING ) {


        SDL_Delay(1000);
    }
}

[ Назад ] Содержание [ Дальше ]


[Назад] Содержание

Использование Simple DirectMedia Layer API

Независимость от порядка байтов

  • Определение порядка байтов в текущей системе

Препроцессор C заменяет SDL_BYTEORDER на SDL_LIL_ENDIAN (младше-конечные) или SDL_BIG_ENDIAN (старше-конечные), в зависимости от порядка байтов в текущей системе.

Младше-конечные системы это те, которые пишут данные на диск размещая так:

     [младшие байты] [старшие байты]
Старше-конечные системы пишут данные на диск так:

     [старшие байты] [младшие байты]

Совет:
В системах x86 младший байт-первый (little-endian), PPC наоборот (big-endian).

 

Example :


 

#include
 "SDL_endian.h"



 

#if
 SDL_BYTEORDER == SDL_LIL_ENDIAN


#define
 SWAP16(X)    (X)


#define
 SWAP32(X)    (X)


#else




#define
 SWAP16(X)    SDL_Swap16(X)


#define
 SWAP32(X)    SDL_Swap32(X)


#endif

 

  • Обмен данных между системами с различным порядком байтов

SDL предоставляет совокупность быстродействующих макросов в SDL_endian.h, SDL_Swap16() и SDL_Swap32(), которые производят обмен данными с указаным вами порядком байтов. Также определены макросы для обмена данными со специфичным для данной системы порядком байтов.

Совет:
Если вам нужно знать порядок байтов в текущей системе, но не нужны все перестановочные функции, подключите SDL_byteorder.h вместо SDL_endian.h

 

Пример :


 

#include
 "SDL_endian.h"



 

void
 ReadScanline16(FILE *file, 
Uint16 *
scanline, 
int
 length)


{



    fread(scanline, length, sizeof(Uint16), file);



   
 

if
 ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) {



        

int
 i;



        

for
 ( i=length-1; i >= 0; --i )



            scanline[i] = SDL_SwapLE16(scanline[i]);



    
}
}

[ Назад ] Содержание


[Назад] Содержание [Дальше]

Использование Simple DirectMedia Layer API

События

  • Ожидание событий

Для ожидания события воспользуйтесь функцией SDL_WaitEvent().

Совет:
SDL имеет международную поддержку клавиатуры, трансляцию событий клавиатуры и помещение эквивалента UNICODE в event.key.keysym.unicode. Так как это требует дополнительной обработки, это должно быть разрешено функцией SDL_EnableUNICODE().

 

Пример :


 

{



    SDL_Event event;



 


    SDL_WaitEvent(&event);



 


    

switch
 (event.type) {



        

case
 SDL_KEYDOWN:



            printf("The %s key was pressed!\n",



                   SDL_GetKeyName(event.key.keysym.sym));



            break;



        

case
 SDL_QUIT:



   
         exit(0);



    
}
}

 

  • Опрос событий

Для опроса событий используйте SDL_PollEvent().

Совет:
Вы можете считывать события из очереди без их удаления оттуда, используя параметр SDL_PEEKEVENT в функции SDL_PeepEvents().

 

Пример :


 

{



    SDL_Event event;



 


    

while
 ( SDL_PollEvent(&event) ) {



        

switch
 (event.type) {



            

case
 SDL_MOUSEMOTION:



                printf("Mouse moved by %d,%d to (%d,%d)\n", 



                       event.motion.xrel, event.motion.yrel,



              
         event.motion.x, event.motion.y);



                break;



            

case
 SDL_MOUSEBUTTONDOWN:



                printf("Mouse button %d pressed at (%d,%d)\n",



                       event.button.button, event.button.x, event.button.y);



             
   break;



            

case
 SDL_QUIT:



                exit(0);



        
}
    }
}

 

  • Опрос состояния событий

В дополнение к обработке событий непосредственно, каждый тип события имеет функцию, которая позволяет проверить состояние приложения. Если вы используете только эту функцию, вы должны игнорировать все события от функции SDL_EventState() и периодически вызывать SDL_PumpEvents() для обработки приложением событий.

Совет:
Вы можете скрывать и показывать системный курсор мыши используя SDL_ShowCursor().

 

Пример :


 

{



    SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);


}



 

void
 CheckMouseHover(void)


{



    

int
 mouse_x, mouse_y;



 


    SDL_PumpEvents();



 


    SDL_GetMouseState(&mouse_x, &mouse_y);



    

if
 ( (mouse_x < 32) && (mouse_y < 32) ) {



        printf("Mouse in upper left hand corner!\n");



    
}
}

[ Назад ] Содержание [ Дальше ]


[ Назад ] Содержание [ Дальше ]

Использование Simple DirectMedia Layer API

Инициализация библиотеки

Используйте SDL_Init() для динамической загрузки и инициализации библиотеки. Эта функция принимает набор флагов, соответствующих частям, которые Вы хотите активизировать:

SDL_INIT_AUDIO

SDL_INIT_VIDEO

SDL_INIT_CDROM

SDL_INIT_TIMER

Используйте SDL_Quit() для выгрузки библиотеки и освобождения ресурсов по окончанию работы.

Совет:
SDL динамически загружает свои библиотеки из стандартного расположения системных библиотек. Используйте функцию SDL_SetLibraryPath() для использования альтернативного размещения динамических библиотек, поставляемых с вашим приложением.

 

Пример :


 

#include
 <stdlib.h>


#include
 "SDL.h"



 

main(


int


 argc, 

char

 *

argv

[])


{



    


if

 ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ) {



        
fprintf(stderr, "Не могу инициализировать SDL: %s\n", SDL_GetError());



        

exit(1);
    }
    
atexit(SDL_Quit);
 
    ...
}

[ Назад ] Содержание [ Дальше ]


[ Назад ] Содержание [ Дальше ]

Использование Simple DirectMedia Layer API

Звук

  • Открытие аудио устройства

Вам необходима callback-функция, которая будет смешивать ваши аудио данные и помещать их в аудио поток. Затем необходимо выбрать желательный аудио формат и частоту, и открыть аудио устройство.

Воспроизведение не начнется до тех пор, пока вы не вызовете SDL_PauseAudio(0). Эта функция позволяет выполнить действия, которые необходимо выполнить до вызова CallBack функции. Как только вы завершите использование звука, закройте его функцией SDL_CloseAudio().

Совет:
Если ваша программа оперирует с различными звуковыми форматами, передайте вторым параметром указатель на SDL_AudioSpec в SDL_OpenAudio(), чтобы получить текущий аппаратный аудио формат. Если же вы оставите второй указатель равным NULL, аудио данные будут конвертированы в аппаратный аудио формат во время выполнения.

 

Пример :


 

#include
 "SDL.h"


#include
 "SDL_audio.h"


{



    extern 
void
 mixaudio(
void *
unused, 
Uint8 *
stream, 

int

 len);



    

SDL_AudioSpec fmt;
 
    
/* Установить 16бит стерео с 22Khz */
    

fmt.freq

 = 22050;



    
fmt.format = AUDIO_S16;



    

fmt.channels = 2;
    
fmt.samples = 512;        
/* Хорошее значение для игр */
    

fmt.callback

 = mixaudio;



    
fmt.userdata = NULL;



 


    

/* открыть аудио усройство и начать воспроизведение! 
*/





    

if
 ( SDL_OpenAudio(&fmt, NULL) < 0 ) {



        
fprintf(stderr, "Не могу открыть аудио: %s\n", SDL_GetError());



        exit(1);



    }



    
SDL_PauseAudio(0);



 


    ...



 


    
SDL_CloseAudio();


}

 

  • Загрузка и воспроизведение звука

Для вашего удобства, SDL предоставляет единственную функцию для загрузки звука, SDL_LoadWAV(). После того, как вы загрузили звук, вы должны преобразовать его к звуковому формату выходного потока с помощью функции SDL_ConvertAudio(), и сделать его доступным для вашей функции микширования.

Совет:
Устройства SDL audio предназначены для низкоуровневого программного аудио микшера. Хорошую реализацию такого микшера, доступную по LGPL лицензии, можно найти в архиве SDL demos.

 

Пример :


 

#define
 NUM_SOUNDS 2



struct

 sample {



    

Uint8 *
data;



    

Uint32
 dpos;



    

Uint32
 dlen;


} sounds[NUM_SOUNDS];



 

void
 mixaudio(
void *
unused, 
Uint8 *
stream, 

int

 len)


{



    


int

 i;



    

Uint32
 amount;



 


    

for
 ( i=0; i<NUM_SOUNDS; ++i ) {



        amount = (sounds[i].dlen-sounds[i].dpos);



        

if
 ( amount > len ) {



       
     amount = len;



        }



        
SDL_MixAudio(stream, &sounds[i].data[sounds[i].dpos], amount, SDL_MIX_MAXVOLUME);



        sounds[i].dpos += amount;



    }


}



 

void
 PlaySound(
char *
file)


{



    


int

 index;



    
SDL_AudioSpec wave;



    

Uint8 *
data;



    

Uint32
 dlen;



    
SDL_AudioCVT cvt;



 


    

/* Найти пустой (или до конца воспроизведенный) звуковой слот */
    
for
 ( index=0; index<NUM_SOUNDS; ++index ) {



        

if
 ( sounds[index].dpos == sounds[index].dlen ) {



            break;



        }



    }



    

if
 ( index == NUM_SOUNDS )



        

return;
 
    
/* Открыть аудио файл и конвертировать его в 16-bit stereo 22kHz */
    
if
 ( SDL_LoadWAV(file, &wave, &data, &dlen) == NULL ) {



        
fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());



        return;



    }



    
SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq,



                            AUDIO_S16,   2,             22050);



    
cvt.buf = malloc(dlen*cvt.len_mult);



    
memcpy(cvt.buf, data, dlen);



    
cvt.len = dlen;



    
SDL_ConvertAudio(&cvt);



    

SDL_FreeWAV(data);
 
    
/* Поместить данные в слот (воспроизведение начнется немедленно) */
    
if
 ( sounds[index].data ) {



        free(sounds[index].data);



    }



    
SDL_LockAudio();



    sounds[index].data = cvt.buf;



    sounds[index].dlen = cvt.len_cvt;



    sounds[index].dpos = 0;



    
SDL_UnlockAudio();


}

[ Назад ] Содержание [ Дальше ]


[Назад] Содержание [Дальше]

Использование Simple DirectMedia Layer API

Потоки

  • Создание простого потока

Создание потока делается через вызов функции SDL_CreateThread(). После успешного возврата из функции ваша функция теперь запущена одновременно с основным приложением в своем контексте задачи (стек, регистры и прочее) и может получать доступ к памяти и открытым файлам используемыми в основном приложении. 

Совет:
Второй аргумент для SDL_CreateThread() передается как параметр для  порожденного потока. Вы можете использовать его для передачи значений в стек или только как указатель на данные, которые будут использоваться в потоке.

 

Пример :

#include
 "SDL_thread.h"



 

int
 global_data = 0;



 

int
 thread_func(
void *
unused)


{


    
int
 last_value = 0;



 

    
while
 ( global_data != -1 ) {


        
if
 ( global_data != last_value ) {


            printf("Data value changed to %d\n", global_data);


            last_value = global_data;


        }


        SDL_Delay(100);


    }


    printf("Thread quitting\n");


    
return
(0);


}



 

{


    SDL_Thread *thread;


    
int
 i;



 

    thread = SDL_CreateThread(thread_func, NULL);


    
if
 ( thread == NULL ) {


        fprintf(stderr, "Unable to create thread: %s\n", SDL_GetError());


        return;


    }



 

    
for
 ( i=0; i<5; ++i ) {


        printf("Changing value to %d\n", i);


        global_data = i;


        SDL_Delay(1000);


    }



 

    printf("Signaling thread to quit\n");


    global_data = -1;


    SDL_WaitThread(thread, NULL);


}

 

  • Синхронизация доступа к ресурсу

Вы можете предотвращать доступ к ресурсу более чем из одного потока с помощью создания семафора и получать доступ к ресурсу, окружая доступ вызовом блокировки (SDL_mutexP()) и разблокировки (SDL_mutexV()).

Совет:
Любые данные, которые могут быть доступны более чем одному потоку одновременно, должны быть защищены семафорами.

 

Пример

#include
 "SDL_thread.h"


#include
 "SDL_mutex.h"



 

int
 potty = 0;


int
 gotta_go;



 

int
 thread_func(
void *
data)


{


    SDL_mutex *lock = (SDL_mutex *)data;


    
int
 times_went;



 

    times_went = 0;


    
while
 ( gotta_go ) {


        SDL_mutexP(lock);    
/* Lock  the potty */


        ++potty;


        printf("Thread %d using the potty\n", SDL_ThreadID());


        
if
 ( potty > 1 ) {


            printf("Uh oh, somebody else is using the potty!\n");


        }


        --potty;


        SDL_mutexV(lock);


        ++times_went;


    }


    printf("Yep\n");


    
return
(times_went);


}



 

{


    
const
 
int
 progeny = 5;


    SDL_Thread *kids[progeny];


    SDL_mutex  *lock;


    
int
 i, lots;



 

    
/* Create the synchronization lock */


    lock = SDL_CreateMutex();



 

    gotta_go = 1;


    
for
 ( i=0; i<progeny; ++i ) {


        kids[i] = SDL_CreateThread(thread_func, lock);


    }



 

    SDL_Delay(5*1000);


    SDL_mutexP(lock);


    printf("Everybody done?\n");


    gotta_go = 0;


    SDL_mutexV(lock);



 

    
for
 ( i=0; i<progeny; ++i ) {


        SDL_WaitThread(kids[i], &lots);


        printf("Thread %d used the potty %d times\n", i+1, lots);


    }
    SDL_DestroyMutex(lock);
}

[ Назад ] Содержание [ Дальше ]


[Назад] Содержание [Дальше]

Использование Simple DirectMedia Layer API

Использование таймеров

  • Получение текущего времени в миллисекундах 

SDL_GetTicks() говорит, сколько миллисекунд прошло с произвольно выбранного момента. 

Совет:
В основном, когда пишутся игры, оптимальным вариантом является движение объектов, основанное на времени (чем на количестве кадров). То есть, при очередном проходе по циклу следует смещать объект не на какое-то постоянное значение, а на значение, пропорциональное прошедшему с последнего прохода по циклу времени. Это позволит держаться игре с постоянной скоростью как на мощных, так и на слабых машинах. 

 

Пример

#define
 TICK_INTERVAL    30



 

Uint32
 TimeLeft(void)


{


    
static
 
Uint32
 next_time = 0;


    
Uint32
 now;



 

    now = SDL_GetTicks();


    
if
 ( next_time <= now ) {


        next_time = now+TICK_INTERVAL;


        
return
(0);


    }


    
return
(next_time-now);


}

 

  • Задержка 

Функция SDL_Delay() позволяет установить задержку на какое-то количество миллисекунд. 

Поскольку ОС, поддерживающие SDL, в большинстве своем многозадачные, вызов это функции не дает гарантии, что программа задержится ровно на данное время! Чаще эта функция просто вызывается для небольшой задержки. 

Совет:
Большинство ОС имеют планировщик временных участков с интервалом около 10 миллисекунд. Вы можете использовать SDL_Delay(1) как способ оставить CPU текущий временной участок, позволив выполниться остальным потокам. Так чаще всего делают, когда необходимо выпонять свой поток в быстром непрерывном цикле, но также необходимо, чтобы и другие потоки (например, аудио) тоже выполнялись.

 

Пример :

{


    
while
 ( game_running ) {


        UpdateGameState();


        SDL_Delay(TimeLeft());
    }
}
 

[Назад] Содержание [Дальше]


[ Назад ] Содержание [ Дальше ]

Использование Simple DirectMedia Layer API

Видео

Выбор и установка разрешения и глубины цвета (простой способ)

Просто выберите свое любимое разрешение и глубину цвета и установите его!

Совет #1:
Вы можете узнать оптимальную глубину, поддерживаемую аппаратурой, используя функцию SDL_GetVideoInfo().

Совет #2:
Вы можете получить список всех поддерживаемых разрешений и соответствующих им глубин цвета, используя функцию SDL_ListModes().

 

Пример :


 

{ SDL_Surface *screen;



 


    screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);



    


if
 ( screen == NULL ) {// Если установить разрешение не удалось
        fprintf(stderr, "Невозможно установить разрешение 640x480: %s\n", SDL_GetError());
        exit(1);
    }
}

 

  • Рисование точек (pixels) на экране

Рисование точек сводится к прямой записи в видеобуфер и вызову функции обновления содержимого экрана.

Совет:
Если вам предстоит рисовать много объектов, лучше заблокировать (lock) экран единожды перед рисованием, вывести все объекты на экран, сохраняя список областей, требующих обновления, и разблокировать (unlock) экран вновь перед обновлением экрана.

 

Пример:

Рисование точки на экране необходимым цветом

 

void

 DrawPixel(SDL_Surface *screen, 
Uint8
 R, 
Uint8
 G, 
Uint8
 B)


{



    

Uint32
 color = SDL_MapRGB(screen->format, R, G, B);



 


    


if

 ( SDL_MUSTLOCK(screen) ) {



        


if

 ( SDL_LockSurface(screen) < 0 ) {


            

return;
        }
    }
    
// Смотрим, сколькими байтами кодируется каждый пиксель (bytes per pixel, bpp)
    

switch

 (screen->format->BytesPerPixel) {



        


case

 1: { 
/* 
Если
 8-bpp */





            

Uint8 *
bufp;



 


            bufp = (
Uint8 *
)screen->pixels + y*screen->pitch + x;



            *bufp = color;



        }



        
break;



 


        


case

 2: { 
/* 
Если
 15-bpp 
или
 16-bpp */





            

Uint16 *
bufp;



 


            bufp = (
Uint16 *
)screen->pixels + y*screen->pitch/2 + x;



            
*bufp = color;
        }
        
break;
 
        

case
 3: { /* Медленный 24-bpp режим, обычно не используется */
            
Uint8 *
bufp;



 


            bufp = (
Uint8 *
)screen->pixels + y*screen->pitch + x;



            *(bufp+screen->format->Rshift/8) = R;



           
 *(bufp+screen->format->Gshift/8) = G;



            *(bufp+screen->format->Bshift/8) = B;



        }



        
break;



 


        


case

 4: { 
/* 
Наверное
, 32-bpp */





            

Uint32 *
bufp;



 


            bufp = (
Uint32 *
)screen->pixels + y*screen->pitch/4 + x;



    
        *bufp = color;



        }



        
break;



    }



    


if

 ( SDL_MUSTLOCK(screen) ) {



        SDL_UnlockSurface(screen);



    }



    SDL_UpdateRect(screen, x, y, 1, 1);


}

 

  • Загрузка и отображение рисунков

Для вашего удобства, SDL предоставляет единственную функцию для загрузки изображений, SDL_LoadBMP(). Библиотека для загрузки изображений может быть найдена в архиве с демонстрациями SDL (SDL demos archive).

Вы можете отобразить загруженную картинку, используя SDL_BlitSurface() для копирования ее в видеобуфер. SDL_BlitSurface() автоматически усекает копируемую область, которая должна быть передана SDL_UpdateRects() для обновления изменившейся части экрана.

Совет #1:
Если вам необходимо показывать некоторую картинку много раз, вы можете ускорить вывод, конвертировав ее в формат дисплея. Для этого используется функция SDL_DisplayFormat()

Совет #2:
Большинство изображений спрайтов имеют прозрачный фон. Вы можете разрешит копирование с прозрачностью (colorkey blit) функцией SDL_SetColorKey().

 

Пример :


 


void

 ShowBMP(

char

 *
file, SDL_Surface *screen, 
int
 x, 
int
 y)


{



    SDL_Surface *image;



    SDL_Rect dest;



 


    

/* Загрузим BMP файл на поверхность */
    
image = SDL_LoadBMP(file);



    


if

 ( image == NULL ) {



        fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());



        

return;
    }
 
    
/* Блитируем (копируем) на экранную поверхность.



       Поверхность не должна быть заблокирована (lo
cked
).



     

*/





    dest.x = x;



    dest.y = y;



    dest.w = image->w;



    dest.h = image->h;



    SDL_BlitSurface(image, NULL, screen, &dest);



 


    

/* 
Обновим
 
измененную
 
часть
 
экрана
 */





    SDL_UpdateRects(screen, 1, &dest);


}

[ Назад ] Содержание [ Дальше ]


[Назад] Содержание [Дальше]

Что она может делать?

Видео

  • Установка видеорежима с любой глубиной цвета (от 8 бит и выше) с необязательным преобразованием, если режим не поддерживается аппаратно.
  • Прямая запись в линейный графический видеобуфер.
  • Создание поверхностей с атрибутами прозрачности или альфа-сопряжения (alpha blending).
  • Копирование поверхностей с автоматическим преобразованием в целевой формат, используя оптимизированные процедуры копирования и, по возможности, аппаратное ускорение. На платформе x86 имеется MMX оптимизированные процедуры копирования.
  • Используется аппаратное ускорение операций копирования и заполнения, если это поддерживается оборудованием.

Совет:
Вы можете установить строку заголовка вашего приложения и иконку, используя функции SDL_WM_SetCaption() и SDL_WM_SetIcon() соответственно.

События

  • Предусмотрены события для:
    • Изменения вида приложения
    • Ввода с клавиатуры
    • Ввода мыши
    • Выхода по требованию пользователя
  • Каждое событие может быть разрешено или запрещено функцией SDL_ EventState ().
  • События передаются через указанную пользователем фильтрующую функцию перед отправлением их во внутреннюю очередь событий.
  • Очередь событий надежна при использовании потоков (t hread-safe).

Совет:
Используйте SDL_ PeepEvents () для поиска событий конкретного типа в очереди событий.

Звук

  • Воспроизведение 8-ми и 16-ти битных звуков, моно или стерео, с необязательным преобразованием, если формат не поддерживается оборудованием.
  • Звук запускается независимо в отдельном потоке, используя для заполнения механизм пользовательской функции обратного вызова (callback).
  • Предназначен для обычного программного аудио микширования, но в архиве с примерами есть полноценная библиотека для вывода музыки и звуков.

Совет:
Используйте функции SDL_ LockAudio () и SDL_ UnlockAudio () для синхронизации доступа к данным, разделяемым между звуковой функцией обратного вызова и остальной частью программы.

CD-ROM аудио

  • Полный API для управления CD аудио

Совет:
Если вы передадите NULL в качестве дескриптора CD-ROM в любую функцию CD-ROM API, это будет действовать как последний открытый CD-ROM.

Потоки

  • Простой API для создания потоков
  • Простые двоичные семафоры для синхронизации

Совет:
Не используйте функции библиотеки C касающиеся ввода/вывода и управления памятью из потоков, если вы можете избежать их- они блокируют ресурсы, используемые другими потоками.

Таймеры

  • Получение прошедшего числа миллисекунд
  • Ожидание указанного числа миллисекунд
  • Установка одиночных периодических таймеров с точностью 10 мс

Совет:
Вы можете спокойно заменить Win32 GetTickCount () на SDL_ GetTicks ().

Независимость от порядка байтов в слове

  • Определение порядка байтов в текущей системе
  • Процедуры для быстрого обмена значений
  • Чтение и запись данных с указанным порядком байтов

Совет:
При чтении ваших файлов данных вам может потребоваться перестановка байтов в 16-битной графике.

[Назад] Содержание [Дальше]


[Назад] Содержание [Дальше]

Что это такое?

SDL - бесплатный кроссплатформенный мультимедийный программный интерфейс приложения
- http://www.libsdl.org/

Используется для создания игр, библиотек для игр, демонстрационных программ, эмуляторов, MPEG плэйеров и других программ.

[Назад] Содержание [Дальше]


[Назад] Содержание [Далее]

На каких платформах выполняется?

Linux

  • Используется X11 в качестве дисплея, беря преимущества XFree86 DGA расширений и новое MTRR ускорение для полноэкранного режима.
  • Используется OSS API для работы со звуком.
  • Потоки обеспечиваются использованием или системным вызовом clone() и SysV IPC, или потоками библиотеки glibc-2.1.

Совет:
Вы можете получить часть скрытого интерфейса драйвера SDL через функцию SDL_GetWMInfo(). Это позволит вам делать вещи наподобие удаления оформления окна и задавать иконку вашего приложения.

Win32

  • Две версии, одна надежная для всех систем, основанна на Win32 API, а другая высокопроизводительная, основанна на DirectX API.
  • Надежная версия использует GDI для отображения графики. Высокопроизводительная версия использует DirectDraw для работы с видео, по возможности используя преимущества аппаратного ускорения.
  • Надежная версия использует waveOut API для воспроизведения звука. Высокопроизводительная версия использует DirectSound для воспроизведения звука.

Совет:
Вы должны периодически вызывать функции обработки событий SDL из вашего главного потока для очистки очереди сообщений Windows, позволяя приложению отзываться на системные сообщения.

BeOS

  • BDirectWindow используется для графики.
  • BSoundPlayer API используется для звука.

Совет:
Linux и BeOS поддерживают флаг SDL_INIT_EVENTTHREAD, который при передачи в SDL_Init() запрашивает запуск обработки очереди сообщений в отдельном потоке. Это полезно для окраски курсора, реагируя, таким образом, когда приложение занято.

MacOS, MacOS X

  • Carbon и DrawSprockets используется для графики.
  • SoundManager API используется для звука.
  • Преимущественно родная поддержка потоков в MacOS X

 

Неофициально перенесены, в процессе переноса

  • Solaris, IRIX, FreeBSD, QNX, OSF/True64

 

[ Назад ] Содержание [ Далее ]