Главная страница
Навигация по странице:

  • Примеры работы со шрифтами

  • Примеры построения графика функции с использованием библиотеки SDL

  • Библиографический список

  • Применение библиотеки SDL для разработка программ на языке C

  • прогинг. Гущин_SDL. Аа нн


    Скачать 1.04 Mb.
    НазваниеАа нн
    Анкорпрогинг
    Дата13.10.2019
    Размер1.04 Mb.
    Формат файлаpdf
    Имя файлаГущин_SDL.pdf
    ТипУчебное пособие
    #89893
    страница7 из 7
    1   2   3   4   5   6   7
    Примеры наложения поверхностей
    Примеры демонстрируют возможные комбинации состояний флагов SDL_SRCCOLORKEY,
    SDL_SRCALPHA, значений полей format→Amask, format→colorkey и format→alpha накладываемой и целевой поверхности и их влияние на результаты:
    #include
    #include
    #include
    #include
    #include const int width = 900, height = 900, depth = 32;
    /* Функция DrawFillRectByCentre заполняет на поверхности surf
    "цветом" color (возможно, с альфа-каналом) прямоугольник с центром в точке x, y, шириной 2*halfw+1 и высотой 2*halfh+1 пиксель. Если такой прямоугольник не умещается на поверхности - ничего не делая, возвращает -2.
    Если не удалось нарисовать, возвращает -1.
    Если все хорошо, возвращает 0. */ int DrawFillRectByCentre(SDL_Surface *surf, Uint16 x,
    Uint16 y, Sint16 halfw, Sint16 halfh, Uint32 color)
    {
    SDL_Rect dst; dst.x = x - halfw; dst.y = y - halfh; dst.w = 2*halfw+1; dst.h = 2*halfh+1; if( dst.x < 0 || dst.y < 0 || dst.w > surf->w || dst.h > surf->h) return -2; else return SDL_FillRect(surf, &dst, color);
    } typedef SDL_Surface* PSurface; int main(int argc, char *argv[])
    { const int SN = 8; /* Количество нижних и верхних поверхностей:
    3 двоичных признака => 2 в кубе */
    SDL_Surface *screen; /* Указатель на поверхность окна */
    SDL_Event event;
    SDL_Surface *upsurf[SN], /* Массивы указателей на верхние и */
    *downsurf[SN]; /* нижние поверхности */
    PSurface results[SN][SN]; /* Результаты */
    Uint32 Rmask, Gmask, Bmask, Amask1, Amask2;
    Uint8 red, green, blue, alpha;
    SDL_Rect background; int i; setbuf(stderr, NULL); /* Отмена буферизации stderr для гарантированного сохранения сообщений об ошибках */ if (SDL_Init(SDL_INIT_VIDEO)) /* инициализация SDL */
    { /* При ошибке формируем сообщение и выходим */ fprintf(stderr,"Ошибка в SDL_Init: %s\n",SDL_GetError()); return 1;

    54
    }
    /* После инициализации собственно SDL: */ screen=SDL_SetVideoMode(width, height, depth, SDL_ANYFORMAT); if (!screen)
    { fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError());
    SDL_Quit(); return 1;
    }
    Rmask = screen->format->Rmask;
    Gmask = screen->format->Gmask;
    Bmask = screen->format->Bmask;
    Amask1 = 0x00000000;
    Amask2 = 0xFF000000; for(i = 0; i < SN; i++) /* Обнуляем массивы указателей:*/ downsurf[i] = upsurf[i] = NULL;
    /* Создаем 8 поверхностей-подложек 81*81 пикселей, по значением бит в i (0 -- не будет, 1 -- будет): бит 0 (самый правый) -- будет ли установлен SDL_SRCCOLORKEY.
    Если будет, то компоненты colorkey имеют значения r,g,b = (65,65,65). Этим цветом рисуется горизонтальная полоса посередине. бит 1 -- будет ли установлен SDL_SRCALPHA. Если да, alpha = 65 бит 2 -- будет ли альфа-канал. Если будет, то вся поверхность непрозрачная, а вертикальная полоса посередине
    -- с прозрачностью 100.*/ for(i = 0; i < SN; i++)
    {
    Uint32 flags, key;
    SDL_Rect dst; flags = SDL_HWSURFACE; flags |= ((i & 1) ? SDL_SRCCOLORKEY : 0); flags |= ((i & 2) ? SDL_SRCALPHA : 0); downsurf[i]=SDL_CreateRGBSurface(flags, 81, 81, 32,
    Rmask, Gmask, Bmask, Amask2 * ((i & 4) == 4)); if(downsurf[i]) /* Проверка создания нижней поверхности */
    {
    SDL_PixelFormat *fmt; fmt = downsurf[i]->format; if(i & 1)/* Установлен ли бит 0 ? (самый младший)*/
    { if(i & 2) /* Установлен ли бит 1 ? (второй справа)*/ key = SDL_MapRGBA(fmt, 65,65,65,128); else key = SDL_MapRGB(fmt, 65,65,65);
    SDL_SetColorKey(downsurf[i], SDL_SRCCOLORKEY, key);
    } if(i & 2) /* Установлен ли бит 1 ? (второй справа)*/
    SDL_SetAlpha(downsurf[i], SDL_SRCALPHA, 128); else /* Принудительно сбрасываем флаг SDL_SRCALPHA */
    SDL_SetAlpha(downsurf[i], 0, 128);
    /* Создаем на поверхности равномерный голубой фон: */
    DrawFillRectByCentre(downsurf[i], 40, 40, 40, 40,
    SDL_MapRGB(fmt, 0, 200, 200));
    /* почти всю поверхность закрашиваем в непрозрачный ярко-красный цвет:*/
    DrawFillRectByCentre(downsurf[i], 40, 40, 32, 32,
    SDL_MapRGB(fmt, 255, 0, 0));
    /* Рисуем горизонтальную непрозрачную серую полосу */
    DrawFillRectByCentre(downsurf[i], 40, 16 + 8, 32, 16,

    55
    SDL_MapRGB(fmt, 65, 65, 65));
    /* Рисуем вертикальную полупрозрачную желтую полосу с прозрачностью 50%*/
    DrawFillRectByCentre(downsurf[i], 16 + 8, 40, 16, 32,
    SDL_MapRGBA(fmt, 255, 255, 0, 128));
    /* Рисуем светло-фиолетовую подложку на месте наложения:*/ background.x = 90 + 45 + i*90 - 40; background.y = 90; background.w = 81; background.h = 81;
    SDL_FillRect(screen, &background,
    SDL_MapRGB(screen->format, 255, 0, 255));
    /* и ее же над ним:*/ background.x = 90 + 45 + i*90 - 40; background.y = 0; background.w = 81; background.h = 81;
    SDL_FillRect(screen, &background,
    SDL_MapRGB(screen->format, 255, 0, 255));
    /* ..и накладываем поверхность на экран:*/ dst.x = 90 + 45 + i*90 - 40; dst.y = 90; dst.w = 81; dst.h = 81;
    SDL_BlitSurface(downsurf[i], NULL, screen, &dst);
    }
    }
    /* Создаем 8 поверхностей-для наложения 57*57 пикселя, по значением бит в i: бит 0 (самый правый) -- будет ли установлен SDL_SRCCOLORKEY?.
    Если будет, то компоненты colorkey имеют значения r,g,b = (200,200,200).Этим цветом рисуется горизонтальная полоса посередине. бит 1 -- будет ли установлен SDL_SRCALPHA. Если да, alpha = 100 бит 2 -- будет ли альфа-канал. Если будет, то вся поверхность непрозрачная и вертикальная полоса посередине с прозрачностью 200. */ for(i = 0; i < SN; i++)
    {
    Uint32 flags, key;
    SDL_Rect dst; flags = SDL_HWSURFACE; flags |= ((i & 1) ? SDL_SRCCOLORKEY : 0x00000000); flags |= ((i & 2) ? SDL_SRCALPHA : 0x00000000); upsurf[i]=SDL_CreateRGBSurface(flags, 57, 57, 32,
    Rmask, Gmask, Bmask, Amask2 * ((i & 4) == 4)); if(upsurf[i])
    {
    SDL_PixelFormat *fmt; fmt = upsurf[i]->format; if(i & 1) /* Установлен ли бит 0 ? (самый младший)*/
    { if(i & 2) /* Установлен ли бит 1 ? */ key = SDL_MapRGBA(fmt, 200,200,200,64); else key = SDL_MapRGB(fmt, 200,200,200);
    SDL_SetColorKey(upsurf[i], SDL_SRCCOLORKEY, key);
    } if(i & 2) /* Установлен ли бит 1 ? */
    SDL_SetAlpha(upsurf[i], SDL_SRCALPHA, 64); else /* Принудительно сбрасываем флаг SDL_SRCALPHA */
    SDL_SetAlpha(upsurf[i], 0, 64);
    /* Создаем на поверхности равномерный белый фон

    56 с зеленоватым оттенком: */
    DrawFillRectByCentre(upsurf[i], 28, 28, 28, 28,
    SDL_MapRGB(downsurf[i]->format, 255, 255, 255));
    /* всю поверхность закрашиваем в непрозрачный ярко-синий цвет:*/
    DrawFillRectByCentre(upsurf[i], 28, 28, 14, 14,
    SDL_MapRGB(upsurf[i]->format, 0, 0, 255));
    /* Рисуем горизонтальную непрозрачную светло-серую полосу */
    DrawFillRectByCentre(upsurf[i], 28, 28, 14, 7,
    SDL_MapRGB(upsurf[i]->format, 200, 200, 200));
    /* Рисуем вертикальную полупрозрачную зеленую полосу с прозрачностью 50*/
    DrawFillRectByCentre(upsurf[i], 28, 28, 7, 14,
    SDL_MapRGBA(upsurf[i]->format, 0, 255, 0, 50));
    /* Рисуем подложку на месте наложения:*/ background.x = 45 - 28; background.y = 2*90 + i*90 + 40 - 28; background.w = 57; background.h = 57;
    SDL_FillRect(screen, &background,
    SDL_MapRGB(screen->format, 90, 90, 165));
    /* ..и накладываем поверхность на экран:*/ dst.x = 45 - 28; dst.y = 2*90 + i*90 + 40 - 28; dst.w = 65; dst.h = 65;
    SDL_BlitSurface(upsurf[i], NULL, screen, &dst);
    }
    }
    /* и еще одну подложку чуть выше мест исходного наложения:*/ background.x = 45 - 28; background.y = 90 + 40 - 28; background.w = 57; background.h = 57;
    SDL_FillRect(screen, &background,
    SDL_MapRGB(screen->format, 90, 90, 165));
    /* Подготавливаем целевые поверхности на базе "подложек" -- используем "преобразование" поверхности для создания копии */ for(i = 0; i { if(downsurf[i])
    {
    Uint32 key; int j; for(j = 0; j < SN; j++)
    { results[j][i] =
    SDL_ConvertSurface(downsurf[i], downsurf[i]->format,downsurf[i]->flags &
    (SDL_HWSURFACE|SDL_SRCCOLORKEY|SDL_SRCALPHA)); if(i & 1) /* Установлен ли бит 0 ? (самый младший)*/
    { if(i & 2) /* Установлен ли бит 1 ? */
    { key = SDL_MapRGBA(results[j][i]->format,
    65,65,65,128); else key = SDL_MapRGB(results[j][i]->format, 65,65,65);
    SDL_SetColorKey(results[j][i], SDL_SRCCOLORKEY, key);
    } if(i & 2) /* Установлен ли бит 1 ? */
    SDL_SetAlpha(results[j][i], SDL_SRCALPHA, 128);

    57 else /* Принудительно сбрасываем флаг SDL_SRCALPHA */
    SDL_SetAlpha(results[j][i], 0, 128);
    }
    }
    }
    }
    /* Накладываем на results[i][j] все upper[i] и выводим результаты: */ for(i = 0; i { int j;
    SDL_Rect dst, resdst, background; for(j = 0; j < SN; j++) if(results[i][j] && upsurf[i])
    { dst.x = 12; /* 40 - 28 */ dst.y = 12; dst.w = 65; dst.h = 65;
    SDL_BlitSurface(upsurf[i], NULL, results[i][j], &dst); resdst.x = 90 + 45 + j*90 - 40; resdst.y = 2*90 + i*90; resdst.w = 81; resdst.h = 81; background = resdst;
    /* Рисуем светло-фиолетовую подложку на месте наложения:*/
    SDL_FillRect(screen, &background,
    SDL_MapRGB(downsurf[i]->format, 255, 0, 255));
    SDL_BlitSurface(results[i][j], NULL, screen, &resdst);
    }
    }
    SDL_Flip(screen); /* Принудительное обновление экрана */
    /* цикл ожидания событий */ while(SDL_WaitEvent(&event))
    { if(event.type == SDL_QUIT ||
    (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
    {
    SDL_Quit(); return 0; /* пусть 0 - нормальное завершение*/
    } if(event.type == SDL_VIDEOEXPOSE)
    SDL_Flip(screen);
    } fprintf(stderr,"WaitEvent failed: %s\n",SDL_GetError());
    SDL_Quit(); return 2; /* Выход с другим кодом ошибки */
    }
    П Р И Л О Ж Е Н И Е 2
    Примеры работы со шрифтами
    #include
    #include
    #include
    #include
    #include int main(int argc, char *argv[])

    58
    {
    SDL_Surface *screen;
    SDL_Event event;
    /* Для вывода текстов */
    TTF_Font *fnt1 = NULL, *fnt2 = NULL, *fnt3 = NULL,
    *fnt4 = NULL, *fnt5= NULL;
    SDL_Color text_color;
    SDL_Rect src;
    SDL_Rect dest;
    SDL_Surface *text_surface1 = NULL;
    SDL_Surface *text_surface2 = NULL;
    SDL_Surface *text_surface3 = NULL;
    SDL_Surface *text_surface4 = NULL;
    SDL_Surface *text_surface5 = NULL;
    /* Строка "Привет, Мир!" в кодировке utf8, сам текст программы в кодировке cp1251 для Dev-Cpp */ char hello_world[]="РџСЂРѐвет, РњРѐСЂ!"; unsigned long vecnt = 0; /* счетчик событий SDL_VIDEOEXPOSE */ setbuf(stderr, NULL); /* Отмена буферизации stderr для гарантированного сохранения сообщений об ошибках*/ if (SDL_Init(SDL_INIT_VIDEO)) /* инициализация SDL */
    { /* При ошибке формируем сообщение и выходим */ fprintf(stderr,"Ошибка в SDL_Init: %s\n",SDL_GetError()); return 1;
    } if (TTF_Init()) /* инициализация SDL_ttf */
    { /* При ошибке формируем сообщение и выходим */ fprintf(stderr,"Ошибка в TTF_Init: %s\n",SDL_GetError()); return 1;
    } atexit(SDL_Quit);
    /* После инициализации собственно SDL и установки atexit(SDL_Quit): */ screen=SDL_SetVideoMode(640,480,32,SDL_ANYFORMAT); if (!screen)
    { fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError()); return 1;
    }
    /* Первый параметр следующей функции должен быть набран в среде разработки на одной строке (весь текст внутри кавычек и сами кавычки)! */
    SDL_WM_SetCaption("РџСЂРѐмер в„–3. Вывод текста разнымРѐ
    шрРѐфтамРѐ СЃ РѐспользованРѐем SDL_ttf", NULL);
    /* Загружаем шрифты с нестандартным размером 29 пунктов, или ближайшим большим, имеющимся в файле шрифта.
    Файлы шрифтов с указанными именами должны быть в каталоге с исполняемым файлом программы! */ fnt1 = TTF_OpenFont("1.ttf", 29); fnt2 = TTF_OpenFont("Anonymous_Pro_I.ttf", 29); fnt3 = TTF_OpenFont("CharisSILR.ttf", 29); fnt4 = TTF_OpenFont("ClearSans-Thin.ttf", 29); fnt5 = TTF_OpenFont("UbuntuMono-RI.ttf", 80);
    /* Если хоть один шрифт не загрузился -- выходим*/ if(!(fnt1 && fnt2 && fnt3 && fnt4 && fnt5)) return 3;
    /* Ввод параметров*/ text_color.r = 0; text_color.g = 255; text_color.b = 0; dest.x = 200; dest.y = 100;
    /* Ширину и высоту выставляем с запасом: */ dest.w = 10; dest.h = 10;

    59 src.x = 0; src.y = 0;
    /* Ширину и высоту выставляем с запасом: */ src.w = 100; src.h = 100;
    /* Текст для корректного отображения должен быть в UTF8! */ text_surface1 = TTF_RenderUTF8_Solid(fnt1,
    "РџСЂРѐвет, РњРѐСЂ!", text_color); if(text_surface1)
    {
    SDL_BlitSurface(text_surface1, &src, screen, &dest);
    SDL_FreeSurface(text_surface1); text_surface1 = NULL;
    }
    /* На основе результатов вывода предыдущего текста смещаем на "строчку" вниз: */ dest.y += dest.h;
    /* Поскольку высота и ширина нового текста может оказаться больше, "восстанавливаем запасы" */ dest.h = dest.w = 1000; text_color.r = 255; text_color.g = 0; text_color.b = 0; text_surface2 = TTF_RenderUTF8_Solid(fnt2,
    "РџСЂРѐвет, РњРѐСЂ!", text_color); if(text_surface2)/* сохраняем для последующего использования.*/
    SDL_BlitSurface(text_surface2, NULL, screen, &dest);
    /* На основе результатов вывода предыдущего текста смещаем на "строчку" вниз: */ dest.y += dest.h;
    /* "восстанавливаем запасы" */ dest.h = dest.w = 1000; text_color.r = 0; text_color.g = 0; text_color.b = 255; text_surface3 = TTF_RenderUTF8_Solid(fnt3, hello_world, text_color); if(text_surface3)
    {
    SDL_BlitSurface(text_surface3, NULL, screen, &dest);
    SDL_FreeSurface(text_surface3); text_surface3 = NULL;
    }
    /* На основе результатов вывода предыдущего текста смещаем на "строчку" вниз: */ dest.y += dest.h;
    /* "восстанавливаем запасы" */ dest.h = dest.w = 1000; text_color.r = 255; text_color.g = 255; text_color.b = 255; text_surface4 = TTF_RenderUTF8_Solid(fnt4, hello_world, text_color); if(text_surface4) /* сохраняем для последующего использования.*/
    SDL_BlitSurface(text_surface4, NULL, screen, &dest);
    /* 5-й шрифт. С каждой перерисовкой изменяется размер, поэтому шрифт переоткрывается. А также цвет -- приходится каждый раз делать новую поверхность. И положение на экране...*/ dest.x = 0; dest.y = 480/2; text_color.r = 255; text_color.g = 255; text_color.b = 255; dest.h = dest.w = 1000; text_surface5 = TTF_RenderUTF8_Solid(fnt5, hello_world, text_color); if(text_surface5)
    {
    SDL_BlitSurface(text_surface5, NULL, screen, &dest);
    SDL_FreeSurface(text_surface5); text_surface5 = NULL;
    }
    TTF_CloseFont(fnt5); /* Закрываем шрифт */ fnt5 = NULL;
    /* Обновление отображения измененной поверхности

    60 на физическом устройстве вывода.
    До этого вызова все операции на поверхности производятся в памяти. */
    SDL_Flip(screen);
    /* цикл ожидания событий */ while(SDL_WaitEvent(&event))
    { if(event.type == SDL_QUIT ||
    (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
    {
    TTF_CloseFont(fnt1); /* Закрываем шрифт */
    TTF_CloseFont(fnt2); /* Закрываем шрифт */
    TTF_CloseFont(fnt3); /* Закрываем шрифт */
    TTF_CloseFont(fnt4); /* Закрываем шрифт */ if(fnt5)
    TTF_CloseFont(fnt5); /* Закрываем шрифт */
    TTF_Quit();
    SDL_Quit(); return 0; /* пусть 0 - нормальное завершение*/
    } if(event.type == SDL_VIDEOEXPOSE)
    {
    ++vecnt; /* Инкремент счетчика событий SDL_VIDEOEXPOSE */ text_color.r = 0; text_color.g = 255; text_color.b = 0; dest.x = 200; dest.y = 100;
    /* Текст для корректного отображения должен быть в UTF8! */ text_surface1 = TTF_RenderUTF8_Solid(fnt1,
    "РџСЂРѐвет, РњРѐСЂ!", text_color); if(text_surface1)
    {
    SDL_BlitSurface(text_surface1, NULL, screen, &dest);
    SDL_FreeSurface(text_surface1); text_surface1 = NULL;
    } dest.y += dest.h;
    /* Отображаем ранее сохраненную поверхность с текстом. */ if(text_surface2)
    SDL_BlitSurface(text_surface2, NULL, screen, &dest);
    /* На основе результатов вывода предыдущего текста смещаем на "строчку" вниз: */ dest.y += dest.h;
    /* "восстанавливаем запасы" */ dest.h = dest.w = 1000; text_color.r = 0; text_color.g = 0; text_color.b = 255; text_surface3 = TTF_RenderUTF8_Solid(fnt3, hello_world, text_color); if(text_surface3)
    {
    SDL_BlitSurface(text_surface3, NULL, screen, &dest));
    SDL_FreeSurface(text_surface3); text_surface3 = NULL;
    }
    /* На основе результатов вывода предыдущего текста смещаем на "строчку" вниз: */ dest.y += dest.h;
    /* "восстанавливаем запасы" */ dest.h = dest.w = 1000;
    /* Отображаем ранее сохраненную поверхность с текстом. */ if(text_surface4)
    SDL_BlitSurface(text_surface4, NULL, screen, &dest));
    /* 5-й шрифт переоткрывается. */ fnt5 = TTF_OpenFont("UbuntuMono-RI.ttf", vecnt*4 % 80);

    61 if(fnt5)
    { text_color.r = vecnt % 3 == 0 ? vecnt*10 % 256 : 0; text_color.g = vecnt % 3 == 1 ? vecnt*10 % 256 : 0; text_color.b = vecnt % 3 == 2 ? vecnt*10 % 256 : 0; text_surface5 = TTF_RenderUTF8_Solid(fnt5, hello_world, text_color); if(text_surface5)
    { dest.x = vecnt*10 % 640; dest.y = 480/2 + vecnt*10 % (480/2); dest.h = dest.w = 1000;
    SDL_BlitSurface(text_surface5, NULL, screen, &dest);
    SDL_FreeSurface(text_surface5); text_surface5 = NULL;
    }
    TTF_CloseFont(fnt5); /* Закрываем шрифт */
    }
    }
    } fprintf(stderr,"WaitEvent failed: %s\n",SDL_GetError());
    SDL_Quit(); return 2; /* Выход с другим кодом ошибки */
    }
    П Р И Л О Ж Е Н И Е 3
    Примеры построения графика функции
    с использованием библиотеки SDL
    Рассмотрим два фрагмента программы с использованием библиотеки SDL_draw, отображающей в окне 640 на 480 пикселей график функции y=ln(|x|), причем x
    min
    = –32, x
    max
    = 32, (MX = MY =
    = 10 пикселей), а экранное положение начала координат – в центре экрана. В первом фрагменте построение производится по точкам с шагом ∆x = 0,001, во втором – отрезками с ∆x = 0,1.
    Инициализация, отображение осей координат, асимптот и т.п. не приводятся.
    /* Отображение графика функции по точкам */
    /* screen – инициализированная поверхность для рисования
    640 на 480 пикселей, */ const Sint16 width=640, heght=480; double xmin=-32.0, xmax=32.0, ymin, ymax; double mx=10.0, my=10.0, dx=0.001, x, y;
    Sint16 x0scr, y0scr, xscr, yscr; x0scr=floor(-1*xmin*mx);
    /* ymin – неизвестно, так нельзя: y0scr=floor(height+ymin*my);
    Используем соглашение о середине экрана: */ y0scr=height/2; /*целочисленное деление */ for(x=xmin;x<=xmax;x+=dx){ if((fabs(x)-1e-4)>0){ /*исключение нуля с учетом погрешности */ y=log(fabs(x)); xscr=x0scr+floor(x*mx); yscr=y0scr-floor(y*my);
    /*Точка синим цветом: */
    Draw_Pixel(screen, xscr, yscr, 0x0000FF);
    }
    }
    /* Отображение графика функции отрезками */
    /* screen – инициализированная поверхность для рисования
    640 на 480 пикселей, */

    62 const Sint16 width=640, heght=480; double xmin=-32.0, xmax=32.0, ymin, ymax; double mx=10.0, my=10.0, dx=0.1, x1, y1, x2, y2;
    Sint16 x0scr, y0scr, xscr1, yscr1, xscr2, yscr2; x0scr=floor(-1*xmin*mx);
    /* ymin – неизвестно, так нельзя: y0scr=floor(height+ymin*my);
    Используем соглашение о середине экрана: */ y0scr=height/2; /*целочисленное деление */ for(x1=xmin, x2=xmin+dx;x10 && (fabs(x2)-1e-4)>0){
    /*исключение нуля с учетом погрешности */ y1=log(fabs(x1)); /*можно исключить повтор вычислений*/ y2=log(fabs(x2)); xscr1=x0scr+floor(x1*mx); yscr1=y0scr-floor(y1*my); xscr2=x0scr+floor(x2*mx); yscr2=y0scr-floor(y2*my);
    /*Отрезок синим цветом: */
    Draw_Line(screen,xscr1,yscr1, xscr2,yscr2,0x0000FF);
    }
    }
    Полный текст примера попеременного рисования графика данной функции обоими способами
    (чередование способа при каждом наступлении события SDL_VIDEOEXPOSE) выглядит следующим образом (приведен текст файла main.c, проект в среде Dev-Cpp 4.9.9.2 создается согласно приложению 1 как консольное приложение Win32 с динамическим подключением библиотек):
    #include
    #include
    #include
    #include "SDL.h"
    #include "SDL_draw.h"
    #include "SDL_ttf.h" void draw_by_pixels(SDL_Surface *who_draw); void draw_by_line(SDL_Surface *who_draw); int main(int argc, char *argv[])
    {
    SDL_Surface *screen;
    SDL_Event event; int flag = 0; if (SDL_Init(SDL_INIT_VIDEO)) /* инициализация SDL */
    { /* При ошибке формируем сообщение и выходим */ fprintf(stderr,"Ошибка в SDL_Init: %s\n",SDL_GetError()); return 1;
    } atexit(SDL_Quit);
    /* После инициализации собственно SDL и установки atexit(SDL_Quit): */ screen=SDL_SetVideoMode(640,480,32,SDL_ANYFORMAT); if (!screen)
    { fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError()); return 1;
    }
    /* Сначала рисуем по точкам синим цветом*/ draw_by_pixels(screen);
    /* цикл ожидания событий */ while(SDL_WaitEvent(&event))

    63
    { if(event.type == SDL_QUIT ||
    (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
    {
    SDL_Quit(); return 0; /* пусть 0 - нормальное завершение*/
    } if(event.type == SDL_VIDEOEXPOSE)
    { /*чередуем способы перерисовки */ if(flag) draw_by_line(screen); else draw_by_pixels(screen); flag = !flag;
    }
    } fprintf(stderr,"WaitEvent failed: %s\n",SDL_GetError());
    SDL_Quit(); return 2; /* Выход с другим кодом ошибки */
    } void draw_by_pixels(SDL_Surface *who_draw)
    {
    /* Отображение графика функции по точкам */ const Sint16 width=640, height=480; double xmin=-32.0, xmax=32.0, ymin, ymax; double mx=10.0, my=10.0, dx=0.001, x, y;
    Sint16 x0scr, y0scr, xscr, yscr; x0scr=floor(-1*xmin*mx);
    /* ymin - неизвестно, следовательно, так нельзя: y0scr=floor(height+ymin*my);
    Используем соглашение о середине экрана: */ y0scr=height/2; /*целочисленное деление */ for(x=xmin;x<=xmax;x+=dx){ if((fabs(x)-1e-4)>0){/*исключение нуля с учетом погрешности */ y=log(fabs(x)); xscr=x0scr+floor(x*mx); yscr=y0scr-floor(y*my);
    /*Точка синим цветом: */
    Draw_Pixel(who_draw, xscr, yscr, 0x0000FF);
    }
    }
    } void draw_by_line(SDL_Surface *who_draw)
    {/* Отображение графика функции отрезками */ const Sint16 width=640, height=480; double xmin=-32.0, xmax=32.0, ymin, ymax; double mx=10.0, my=10.0, dx=0.1, x1, y1, x2, y2;
    Sint16 x0scr, y0scr, xscr1, yscr1, xscr2, yscr2; x0scr=floor(-1*xmin*mx);
    /* ymin - неизвестно, так нельзя: y0scr=floor(height+ymin*my);
    Используем соглашение о середине экрана: */ y0scr=height/2; /*целочисленное деление */ for(x1=xmin, x2=xmin+dx;x10 && (fabs(x2)-1e-4)>0){
    /*исключение нуля с учетом погрешности */ y1=log(fabs(x1)); /*можно исключить повтор вычислений*/ y2=log(fabs(x2)); xscr1=x0scr+floor(x1*mx); yscr1=y0scr-floor(y1*my); xscr2=x0scr+floor(x2*mx);

    64 yscr2=y0scr-floor(y2*my);
    /*Отрезок красным цветом: */
    Draw_Line(who_draw,xscr1,yscr1, xscr2,yscr2,0xFF0000);
    }
    }
    }
    В качестве второго примера рассмотрим рисование графика функции y=a+b/(x*c+d) на отрезке
    [xmin; xmax] с использованием максимальной площади экрана. При этом все параметры вводятся пользователем с клавиатуры. Отображение осей координат, асимптот и т.п. не приводится.
    #include
    #include
    #include
    #include
    #include "SDL.h"
    #include "SDL_draw.h"
    #include "SDL_ttf.h" void draw_by_pixels(SDL_Surface *who_draw); void draw_by_line(SDL_Surface *who_draw);
    /*Вывод рационального числа с экранным редактированием. Параметры: где рисовать (поверхность), каким шрифтом, каким цветом, в какой прямоугольной области можно отображать вводимые данные, исходное значение (значение по умолчанию) */ double input_double(SDL_Surface *who_draw, TTF_Font *fnt,
    SDL_Color color, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, double defval);
    /* Параметры функции и значения по умолчанию*/ double a=0, b=1, c=1, d=0; const Sint16 width=640, height=480; double xmin=-32.0, xmax=32.0, ymin, ymax; double mx=10.0, my=10.0;
    Sint16 x0scr, y0scr; int main(int argc, char *argv[])
    {
    SDL_Surface *screen;
    SDL_Event event;
    TTF_Font *fnt;
    /* Для вывода текстов */
    SDL_Color text_color;
    SDL_Rect dest;
    SDL_Surface *text_surface = NULL; char txtbuf[100]; int flag = 0; /* очередность использования методов рисования*/ setbuf(stderr, NULL); /* Отмена буферизации stderr для гарантированного сохранения сообщений об ошибках*/ if (SDL_Init(SDL_INIT_VIDEO)) /* инициализация SDL */
    { /* При ошибке формируем сообщение и выходим */ fprintf(stderr,"Ошибка в SDL_Init: %s\n",SDL_GetError()); return 1;
    } if (TTF_Init()) /* инициализация SDL_ttf */
    { /* При ошибке формируем сообщение и выходим */ fprintf(stderr,"Ошибка в TTF_Init: %s\n",SDL_GetError());

    65 return 1;
    } atexit(SDL_Quit);
    /* После инициализации собственно SDL и установки atexit(SDL_Quit): */ screen=SDL_SetVideoMode(640,480,32,SDL_ANYFORMAT); if (!screen)
    { fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError()); return 1;
    }
    /* Первый параметр должен быть полностью на одной строке вместе с кавычками! */
    SDL_WM_SetCaption("ПостроенРѐРµ
    графРѐРєР°
    функцРѐРѐ
    СЃ
    РѐспользованРѐем SDL. РџСЂРѐмер в„–2",NULL);
    /* Загружаем шрифт размером sz пунктов*/ fnt = TTF_OpenFont("ClearSans-Thin.ttf", 30); printf("fnt = %p\n", fnt); if(!fnt) return 3;
    /* Цвета для ввода параметров (ярко-зеленый): */ text_color.r = 0; text_color.g = 255; text_color.b = 0;
    /* Ввод параметров: */ dest.x = 0; dest.y = 0; text_surface = TTF_RenderUTF8_Solid(fnt, "a=", text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    }
    SDL_Flip(screen); a = input_double(screen, fnt, text_color, dest.x+dest.w, dest.y, dest.x+dest.w + 200, dest.y+dest.h, a); dest.x = 0; dest.y = dest.y + dest.h; text_surface = TTF_RenderUTF8_Solid(fnt, "b=", text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    }
    SDL_Flip(screen); b = input_double(screen, fnt, text_color, dest.x+dest.w, dest.y, dest.x+dest.w + 200, dest.y+dest.h, b); dest.x = 0; dest.y = dest.y + dest.h; text_surface = TTF_RenderUTF8_Solid(fnt, "c=", text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    }
    SDL_Flip(screen); c = input_double(screen, fnt, text_color, dest.x+dest.w, dest.y, dest.x+dest.w + 200, dest.y+dest.h, c); dest.x = 0; dest.y = dest.y + dest.h; text_surface = TTF_RenderUTF8_Solid(fnt, "d=", text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    } printf("before input_double(), d=%lf\n",d);
    SDL_Flip(screen); d = input_double(screen, fnt, text_color, dest.x+dest.w, dest.y, dest.x+dest.w + 200, dest.y+dest.h, d); dest.x = 0; dest.y = dest.y + dest.h; text_surface = TTF_RenderUTF8_Solid(fnt, "xmin=", text_color); if(text_surface){

    66
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    }
    SDL_Flip(screen); xmin = input_double(screen, fnt, text_color, dest.x+dest.w, dest.y, dest.x+dest.w + 200, dest.y+dest.h, xmin); dest.x = 0; dest.y = dest.y + dest.h; text_surface = TTF_RenderUTF8_Solid(fnt, "xmax=", text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    }
    SDL_Flip(screen); xmax = input_double(screen, fnt, text_color, dest.x+dest.w, dest.y, dest.x+dest.w + 200, dest.y+dest.h, xmax);
    /* Расчет масштабных коэффициентов:*/ mx = (1.0 * width) / fabs(xmax-xmin); dest.x = 0; dest.y = dest.y + dest.h; memset(txtbuf,0,100); sprintf(txtbuf,"mx = %lf",mx); text_surface = TTF_RenderUTF8_Solid(fnt, txtbuf, text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    } dest.x = 0; dest.y = dest.y + dest.h; memset(txtbuf,0,100); sprintf(txtbuf,"my = %lf",my); text_surface = TTF_RenderUTF8_Solid(fnt, txtbuf, text_color); if(text_surface){
    SDL_BlitSurface(text_surface, NULL, screen, &dest);
    SDL_FreeSurface(text_surface); text_surface = NULL;
    }
    /* Сначала рисуем по точкам синим цветом*/ draw_by_pixels(screen);
    SDL_Flip(screen);
    /* цикл ожидания событий */ while(SDL_WaitEvent(&event))
    { if(event.type == SDL_QUIT ||
    (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
    {
    TTF_CloseFont(fnt); /* Закрываем шрифт */
    SDL_Quit(); return 0; /* пусть 0 - нормальное завершение*/
    } if(event.type == SDL_VIDEOEXPOSE)
    { /*чередуем способы перерисовки */ if(flag) draw_by_line(screen); else draw_by_pixels(screen); flag = !flag;
    }
    } fprintf(stderr,"WaitEvent failed: %s\n",SDL_GetError());
    SDL_Quit(); return 2; /* Выход с другим кодом ошибки */
    } void draw_by_pixels(SDL_Surface *who_draw)
    {/* Отображение графика функции по точкам */ double dx=0.001, x, y;
    Sint16 xscr, yscr;

    67 x0scr=floor(-1*xmin*mx);
    /* ymin - неизвестно, так нельзя: y0scr=floor(height+ymin*my);
    Используем соглашение о середине экрана: */ y0scr=height/2; /*целочисленное деление */ for(x=xmin; x<=xmax; x+=dx){ if((fabs(x)-1e-4)>0){ /*исключение нуля */ y=a+b/(c*x+d); xscr=x0scr+floor(x*mx); yscr=y0scr-floor(y*my);
    /* рисуем синим цветом только точки, помещающиеся на поверхности, иначе будет ошибка*/ if( 0<=xscr && xscr Draw_Pixel(who_draw, xscr, yscr, 0x0000FF);
    }
    }
    } void draw_by_line(SDL_Surface *who_draw)
    {/* Отображение графика функции отрезками */ double dx=0.1, x1, y1, x2, y2;
    Sint16 xscr1, yscr1, xscr2, yscr2; x0scr=floor(-1*xmin*mx);
    /* ymin - неизвестно, так нельзя: y0scr=floor(height+ymin*my);
    Используем соглашение о середине экрана: */ y0scr=height/2; /*целочисленное деление */ for(x1=xmin, x2=xmin+dx;x10 && (fabs(x2)-1e-4)>0){
    /*исключение нуля */ y1=a+b/(c*x1+d); /*можно исключить повтор вычислений*/ y2=a+b/(c*x2+d); xscr1=x0scr+floor(x1*mx); yscr1=y0scr-floor(y1*my); xscr2=x0scr+floor(x2*mx); yscr2=y0scr-floor(y2*my);
    /*Отрезок красным цветом (для отрезков больше проверок:*/ if( 0<=xscr1 && xscr1 0<=xscr2 && xscr2 Draw_Line(who_draw,xscr1,yscr1,xscr2,yscr2,0xFF0000);
    }
    }
    }
    /* Функция вывода на поверхность одиночного символа заданным шрифтом в указанных координатах заданным цветом */ void OutSymbolFntColorXY(SDL_Surface *screen, TTF_Font *fnt,
    SDL_Color clr, Sint16 x, Sint16 y, int symbolcode)
    { /* Такая реализация корректно работает только с символами, код которых в utf8 задается 1 байтом. То есть, только символами ASCII, имеющими код от 0 до 127. Этого достаточно для записи вещественных чисел. */
    SDL_Rect dest; dest.x = x; dest.y = y; сhar s[2]; s[0]=symbolcode; s[1]='\0';
    SDL_Surface *TextSurface = TTF_RenderUTF8_Solid(fnt, s, clr);
    SDL_BlitSurface(TextSurface, NULL, screen, &dest);
    SDL_FreeSurface(TextSurface); // Освобождаем поверхность
    /* Обновляем только измененный участок целевой поверхности:*/
    SDL_UpdateRect(screen,dest.x,dest.y,dest.w,dest.h);
    }
    /* Функция ввода вещественного числа. Параметры см. выше при объявлении.*/ double input_double(SDL_Surface *who_draw, TTF_Font *fnt,
    SDL_Color color, Sint16 x1, Sint16 y1,
    Sint16 x2, Sint16 y2, double defval)
    {

    68
    #define WHOLE 7 //кол-во знаков под целую часть мантиссы
    #define FRACTIONAL 6 //кол-во знаков под дробную часть мантиссы
    #define EXP 3 //кол-во знаков под степень
    #define E 308 //максимальное значение степени
    /* Символьный буфер для ввода и редактирования: размер исходя из заданного числа знаков, а также места по одному байту для возможного знака мантиссы и показателя, десятичной точки в мантиссе, разделителя мантиссы и показателя и завершающего NULL-терминатора.*/ char s[WHOLE+FRACTIONAL+EXP+5];
    /* Все символы в нем делаем нулевыми */ memset(s,0,WHOLE+FRACTIONAL+EXP+5);
    /* количество и положение различных символов в буфере */ int _kol=-1, _whole=0, _fractional=0, _exp=0,
    _pointf=0,_minusf=0,_ef=0,_minusEf=0;
    /* Координаты рабочей области */
    Sint16 wrk_x1=x1, x=wrk_x1, wrk_y1=y1, y=wrk_y1;
    SDL_Event event; int i; while ( SDL_WaitEvent(&event) ){ if (event.type == SDL_QUIT){
    /* По идее, надо вернуть его обратно в очередь и пусть обрабатывает основная программа...
    В данном примере не реализовано. */ break;
    } if (event.type == SDL_KEYDOWN){ /*Если нажата клавиша...*/ if((!_pointf && _whole (_pointf && _fractional (_ef && _exp {/*При соблюдении условий смотрим, не цифра ли нажата...*/ if(event.key.keysym.sym >= SDLK_0 && event.key.keysym.sym <=SDLK_9)
    {// Цифровую клавиатуру пока игнорируем char digitsym = (char) event.key.keysym.sym;
    OutSymbolFntColorXY(who_draw, fnt, color, x,y, digitsym); x+=20; s[++_kol]=digitsym; if(!_pointf && _whole _whole=_whole+1; else if(_pointf && _fractional _fractional=_fractional+1; else
    _exp=_exp+1;
    }
    } if ((event.key.keysym.sym==SDLK_BACKSPACE)&&(x!=x1))
    { if(_whole<=WHOLE && !_pointf && !_ef && _whole>0 &&
    !_fractional)
    _whole=_whole-1; //удаление цифры из целой части else if(_pointf && _fractional>0 &&
    _fractional<=FRACTIONAL && !_ef && _whole)
    _fractional=_fractional-1;/*удаление цифры из дробной части мантиссы */ else if(!_whole && _minusf)
    _minusf=0; // удаление минуса перед целой частью else if (_pointf && !_fractional && !_ef && _whole)
    _pointf=0; //удаление точки else

    69 if (_ef && !_exp && !_minusEf)
    _ef=0; //удаление символа exp else if (_ef && !_exp && _minusEf)
    _minusEf=0; //удаление минуса после exp else if (_ef && _exp<=EXP)
    _exp=_exp-1; //удаление цифры в степени
    // Смещаемся на 20 пикселей влево (одно "знакоместо") x-=20;
    // Затираем знакоместо черным цветом
    Draw_FillRect(who_draw,x,y,20,42,0);
    // Обновляем экран
    SDL_UpdateRect(who_draw,0,0,width,height);
    _kol=_kol-1; /* Уменьшаем число символов */ continue; /*Продолжаем ожидание событий */
    } if(event.key.keysym.sym==SDLK_MINUS &&
    ((!_minusf && !_whole && !_ef) ||
    (!_minusEf && _ef && !_exp)))
    {
    OutSymbolFntColorXY(who_draw, fnt, color, x,y,SDLK_MINUS); x+=20; s[++_kol]=45; if (!_minusf && !_whole && !_ef)
    _minusf=1; else
    _minusEf=1; continue;
    } if (event.key.keysym.sym==SDLK_PERIOD && !*pointf && !_ef){ if (!_whole){ s[++_kol]=48; _whole=1;
    OutSymbolFntColorXY(who_draw,fnt,color,x,y,SDLK_0);
    } s[++_kol]=46;
    OutSymbolFntColorXY(who_draw, fnt, color,x,y,SDLK_PERIOD); x+=20;
    _pointf=1; continue;
    } if (event.key.keysym.sym==SDLK_e && !_ef){
    OutSymbolFntColorXY(who_draw, fnt, color,x,y,SDLK_e); x+=20; s[++_kol]=101; _ef=1; continue;
    } if (event.key.keysym.sym==SDLK_RETURN && _kol!=-1)
    { /* Завершение ввода */ double tmp; s[_kol+1]='\0'; sscanf(s,"%lf",&tmp); /*Отсутствует проверка ввода! */ return tmp;
    } if (event.key.keysym.sym == SDLK_ESCAPE)
    /* Будет возвращено значение по умолчанию. */ break;
    } /* Конец обработки события SDL_KEYDOWN */
    } /* Конец цикла обработки событий */ return defval;
    } /* конец тела функции input_double */
    Библиографический список

    70 1. Керниган, Брайен, Ритчи, Деннис. Язык программирования C. 2-е изд.: пер. с англ. М.: Изд. дом «Вильямс»,
    2013. 304 с.
    2. SDL Library Documentation. URL: www.libsdl.org/release/SDL-1.2.15/docs/ html/index.html (дата обращения:
    28.11.2013).

    О Г Л А В Л Е Н И Е
    Введение. Работа с клавиатурой и дисплеем ............................................................. 3 1. Основные возможности библиотеки семейства SDL ............................................. 8 2. Начало работы с SDL 1.2.15, SDL_draw 1.2.13 и SDL_ttf 2.0.11 в интегри-рованной среде разработки Dev-Cpp
    4.9.9.2 под управлением Windows XP ................................................................... 9 3. Подключение и инициализация библиотеки SDL ................................................ 13 4. Графические примитивы библиотеки SDL_draw ................................................. 17 5. Рисование сложных фигур ..................................................................................... 19 6. Работа с поверхностями в библиотеке SDL .......................................................... 30 7. Имитация движения при выводе на дисплей ........................................................ 38 8. Вывод текста с помощью библиотеки SDL_ttf ..................................................... 43 9. Обработка событий средствами библиотеки SDL ................................................ 46 10. Построение графиков функций на дискретных устройствах отображения информации 51
    П р и л о ж е н и е 1. Примеры наложения поверхностей ....................................... 53
    П р и л о ж е н и е 2. Примеры работы со шрифтами .............................................. 57
    П р и л о ж е н и е 3. Примеры построения графика функции с использова-нием библиотеки SDL
    61
    Библиографический список......................................................................................... 69
    Гущин Артем Николаевич
    Применение библиотеки SDL для разработка программ
    на языке C
    Редактор Г.М. Звягина
    Корректор Л.А. Петрова
    Подписано в печать 9.10.2014. Формат бумаги 60х84/16. Бумага документная.
    Печать трафаретная. Усл. печ. л. 6,85. Тираж 100 экз. Заказ № 150.
    Балтийский государственный технический университет
    Типография БГТУ
    190005, С.-Петербург, 1-я Красноармейская ул., д.1
    1   2   3   4   5   6   7


    написать администратору сайта