SDL - Simple DirectMedia Layer
http://www.libsdl.org/
SDL - бесплатный кроссплатформенный мультимедийный программный интерфейс. Как следует из названия, функции SDL оперируют структурами, максимально приближенными к аппаратному обеспечению мультимедиа-средств, что позволяет существенно повысить производительность приложений, использующих мультимедиа (игры, медиа-плееры и т. п.)
Интерфес SDL делится на несколько подсистем: видео, события (клавиатура
и мышь), звук, CD-ROM аудио, таймеры, нити (threads). Видео-подсистема SDL
предоставляет возможность использования видеорежима с любой глубиной цвета
(от 8 бит и выше), при необходимости используя преобразование, если режим
не поддерживается аппаратно; обеспечивает прямой доступ в линейный графический
видеобуфер; позволяет работать с атрибутами прозрачности или альфа-сопряжения
(alpha blending); использует аппаратное ускорение для операций копирования,
заполнение и преобразования (например, оптимизация под MMX на x86).
| При компиляции программ на Си, использующих SDL, компилятору необходимо
передавать дополнительную опцию -lSDL:
gcc sdlex.c -lSDL |
Перед использованием функций SDL следует инициализировать библиотеку
при помощи функции SDL_Init, ее параметр - битовое поле, отражающее,
какие подсистемы SDL приложение собирается задействовать. Для вычисления этого
параметра удобно использовать константы SDL_INIT_AUDIO, SDL_INIT_VIDEO,
SDL_INIT_CDROM, SDL_INIT_TIMER, которые, при необходимости, объединяются
побитовым "ИЛИ". Для выгрузки библиотеки и освобождения ресурсов по окончанию
работы используется процедура SDL_Quit. Если в процессе работы
с библиотекой возникает ошибка, то ее текстовое описание можно получить при
помощи SDL_GetError.
uses SDL; function SDL_Init(flags:Uint32):integer; procedure SDL_Quit; function SDL_GetError:PChar; | #include <SDL/SDL.h> int SDL_Init(Uint32 flags); void SDL_Quit(void); char *SDL_GetError(void); |
| Во FreePascal процедуры и функциии каждой подсистемы объявлены в отдельных модулях, поэтому, кроме модуля SDL, необходимо подключать еще и модули используемых подсистем (например, SDL_Video, SDL_Audio,...) | В Си в зависимости от версии и платформы, возможно, потребуется подключить заголовочные файлы подсистем SDL ("SDL_video.h", "SDL_audio.h",...), если это не делается в основном файле "SDL.h". |
Видео-подсистема SDL оперирует структурами SDL_Surface ("поверхность"). Поверхность представляет область "графической" памяти, кодирующей изображение. Эта структура содержит следующие поля:
- flags - битовое поле, характеризующее свойства поверхности: SDL_SWSURFACE (буфер в системной памяти), SDL_HWSURFACE (буфер в видеопамяти), SDL_ASYNCBLIT (асинхронные операции), SDL_FULLSCREEN (полноэкранный режим), SDL_OPENGL (поверхность контекста OpenGL), SDL_HWACCEL (использовать аппаратное ускорение) и др.
- format - указатель на структуру SDL_PixelFormat, описывающую формат кодирования цвета пикселов (наиболее полезное поле в этой структуре - BytesPerPixel - количество байт, отводимых под пиксел в графическом буфере поверхности.
- w, h - размеры изображения (в пикселах).
- pitch - размер (в байтах) одной строки пикселов изображения.
- pixels - указатель на графический буфер поверхности.
|
function SDL_SetVideoMode(width,height:integer; bpp:integer; flags:Uint32):PSDL_Surface; function SDL_GetVideoSurface:PSDL_Surface; |
SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); SDL_Surface *SDL_GetVideoSurface(void); |
Кроме дисплейной поверхности (связанной с видеобуфером) программа может
оперировать неотображаемыми поверхностями. Создать пустую неотображаемую
поверхность можно при помощи функций SDL_CreateRGBSurface и (непустую)
SDL_CreateRGBSurfaceFrom. Можно также создать поверхность и заполнить
ее изображение из графического файла в формате BMP. Кроме того, SDL поддерживает
сохрание изображения поверхности в BMP-файле. Для копирования изображения между
поверхностями можно использовать SDL_BlitSurface. Параметры SDL_Rect
задают положение и размер копируемых областей. В случае дисплейной поверхности,
чтобы изменения вступили в силу, надо обновить отображаемую область при помощи
SDL_UpdateRect или SDL_UpdateRects. Если вы копируете
изображение на дисплейную поверхность, для ускорения копирования можно
предварительно конвертировать исходную поверхность в формат дисплейной
поверхности - SDL_DisplayFormat. Для конвертирования поверхности
в произвольный формат предназначена функция SDL_ConvertSurface.
При завершении работы необходимо освободить память от каждой из неотображаемых
поверхностей при помощи процедуры SDL_FreeSurface.
|
function SDL_LoadBMP(file:PChar):PSDL_Surface; function SDL_SaveBMP(surface:PSDL_Surface; file:PChar):integer; function SDL_BlitSurface(src:PSDL_Surface; srcrect:PSDL_Rect; dst:PSDL_Surface; dstrect:PSDL_Rect):integer; procedure SDL_UpdateRect(screen:PSDL_Surface; x,y:Sint32; w,h:Sint32); procedure SDL_UpdateRects(screen:PSDL_Surface; numrects:integer; var rects:SDL_RectArray); function SDL_DisplayFormat(surface:PSDL_Surface):PSDL_Surface; procedure SDL_FreeSurface(surface:PSDL_Surface); |
SDL_Surface *SDL_LoadBMP(const char *file); int SDL_SaveBMP(SDL_Surface *surface, const char *file); int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect); void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h); void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects); SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface); void SDL_FreeSurface(SDL_Surface *surface); |
Приведенная ниже программа загружает из файла картинку в
BMP-формате и отображает ее в разных местах дисплейной поверхности.
program gr1;
uses SDL, SDL_Video;
var
screen,img:PSDL_Surface;
r:SDL_Rect;
i:integer;
begin
if SDL_Init(SDL_INIT_VIDEO)<>0 then begin
writeln('SDL_Init failed: ',SDL_GetError);
halt(1);
end;
screen:=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
if screen=nil then begin
writeln('SDL mode failed: ',SDL_GetError);
halt(1);
end;
img:=SDL_LoadBMP('img_ex.bmp');
if img=nil then begin
writeln('Picture is not available!');
halt(2);
end;
r.w:=img^.w; r.h:=img^.h;
SDL_SetColorKey(img,SDL_SRCCOLORKEY,
SDL_MapRGB(img^.format,179,217,255));
for i:=0 to 20 do begin
r.x:=i*20; r.y:=i*20;
SDL_BlitSurface(img,nil,screen,@r);
end;
SDL_UpdateRect(screen,0,0,640,480);
readln;
SDL_FreeSurface(img);
SDL_Quit;
end.
|
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_video.h>
SDL_Surface *screen,*img;
SDL_Rect r;
int i;
int main() {
if (SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr,"SDL_Init failed: %s\n",SDL_GetError());
return 1;
}
screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
if (!screen) {
fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError());
return 1;
}
img=SDL_LoadBMP("img_ex.bmp");
if (!img) {
fprintf(stderr,"Picture is not available!\n");
return 2;
}
r.w=img->w; r.h=img->h;
SDL_SetColorKey(img,SDL_SRCCOLORKEY,
SDL_MapRGB(img->format,179,217,255));
for (i=0; i<400; i+=20) {
r.x=r.y=i;
SDL_BlitSurface(img,NULL,screen,&r);
}
SDL_UpdateRect(screen,0,0,640,480);
getchar();
SDL_FreeSurface(img);
SDL_Quit();
}
|
В данной программе используется функция SDL_SetColorKey, которая
позволяет задать ключевой цвет (цвет, соответствующий прозрачному). Ключевой
цвет (параметр key) задается в формате кодирования цвета для данной поверхности.
Для преобразования цвета из RGB-компонент в заданный формат кодирования удобно
использовать функцию SDL_MapRGB. Формат кодирования обычно задается
полем format структуры SDL_Surface. Данная функция возвращает цвет пиксела в
формате поверхности. Следует иметь в виду, что при записи в видеобуфер надо
использовать лишь SDL_PixelFormat->BitsPerPixel бит данного значения,
игнорируя старшие биты, в противном случае может быть испорчена информация
о цвете для последующих пикселов.
|
function SDL_SetColorKey(surface:PSDL_Surface; flag:Uint32; key:Uint32):integer; function SDL_MapRGB(fmt:PSDL_PixelFormat; r,g,b:Uint8):Uint32; |
int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key); Uint32 SDL_MapRGB(SDL_PixelFormat *fmt, Uint8 r, Uint8 g, Uint8 b); |
Для построения произвольных изображений необходимо непосредственно обращаться
к видеопамяти поверхности (по адресу pixels структуры SDL_Surface).
Перед изменением буфера необходимо заблокировать поверхность
при помощи SDL_LockSurface, а когда изменения закончены -
разблокировать (SDL_UnlockSurface). Между операциями блокирования /
разблокирования не следует выполнять никаких системных или библиотечных вызовов.
|
function SDL_LockSurface(surface:PSDL_Surface):integer; procedure SDL_UnlockSurface(surface:PSDL_Surface); |
int SDL_LockSurface(SDL_Surface *surface); void SDL_UnlockSurface(SDL_Surface *surface); |
Приведенная ниже программа строит три вложенных окружности разного цвета.
В примере приводится процедура putpixel, пригодная для режимов с глубиной
цвета 32 бита.
program gr1;
uses SDL,SDL_Types,SDL_Video;
type parr=array [0..1] of byte;
var screen:PSDL_Surface;
x,y:real;
const t:real=0;
procedure putpixel(s:PSDL_Surface; x,y:integer; r,g,b:Uint8);
var ptr:^Uint32;
begin
ptr:=addr(parr(s^.pixels^)
[s^.pitch*y+s^.format^.BytesPerPixel*x]);
ptr^:=SDL_MapRGB(s^.format,r,g,b);
end;
begin
if SDL_Init(SDL_INIT_VIDEO)<>0 then begin
writeln('SDL_Init failed: ',SDL_GetError);
halt(1);
end;
screen:=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
if screen=nil then begin
writeln('SDL mode failed: ',SDL_GetError);
halt(1);
end;
SDL_WM_SetCaption('circles',nil);
SDL_LockSurface(screen);
while t<2*3.1416 do begin
x:=20*cos(t); y:=20*sin(t);
putpixel(screen,round(x+320),round(y+200),255,0,0);
putpixel(screen,round(2*x+320),round(2*y+200),0,255,0);
putpixel(screen,round(3*x+320),round(3*y+200),0,0,255);
t:=t+0.0001;
end;
SDL_UnlockSurface(screen);
SDL_UpdateRect(screen,0,0,640,480);
readln;
SDL_Quit;
end.
|
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_video.h>
SDL_Surface *screen;
float t=0,x,y;
void putpixel(SDL_Surface *s,
int x, int y, Uint8 r, Uint8 g, Uint8 b)
{
void *ptr=(char*)(s->pixels)+
s->pitch*y+s->format->BytesPerPixel*x;
*(Uint32*)ptr=SDL_MapRGB(s->format,r,g,b);
}
int main() {
if (SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr,"SDL_Init failed: %s\n",SDL_GetError());
return 1;
}
screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
if (!screen) {
fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError());
return 1;
}
SDL_WM_SetCaption("circles",NULL);
SDL_LockSurface(screen);
while (t<2*3.1416) {
x=20*cos(t); y=20*sin(t);
putpixel(screen,x+320,y+200,255,0,0);
putpixel(screen,2*x+320,2*y+200,0,255,0);
putpixel(screen,3*x+320,3*y+200,0,0,255);
t+=0.0001;
}
SDL_UnlockSurface(screen);
SDL_UpdateRect(screen,0,0,640,480);
getchar();
SDL_Quit();
}
|
SDL предоставляет небольшой набор функций управления оконным интерфейсом:
SDL_WM_SetCaption - изменить заголовок окна,
SDL_WM_GetCaption - получить заголовок окна,
SDL_WM_ToggleFullScreen - переключиться из оконного режима
в полноэкранный и обратно и некоторые другие.
|
procedure SDL_WM_SetCaption(title,icon:PChar); procedure SDL_WM_GetCaption(var title,icon:PChar); function SDL_WM_ToggleFullScreen(surface:PSDL_Surface):integer; |
void SDL_WM_SetCaption(const char *title, const char *icon); void SDL_WM_GetCaption(char **title, char **icon); int SDL_WM_ToggleFullScreen(SDL_Surface *surface); |
