Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Гущин_SDL.pdf
Скачиваний:
168
Добавлен:
17.03.2018
Размер:
1.09 Mб
Скачать

SDL_FillRect(screen, &r, 0x000000FF); /* ярко-синий */ SDL_UnlockSurface(screen); SDL_UpdateRect(screen,0,0,max_x,max_y);

/* Задержка на опрос событий составляет около 10 мс или более, в зависимости от производительности компьютера. При необходимости возможна дополнительная задержка */

}

SDL_Quit();

return 0; /* Нормальное завершение */

Аналогичным образом могут обрабатываться и иные события.

10.Построение графиков функций на дискретных устройствах отображения информации

Сточки зрения математики, график функции y = f(x), где x,y R, есть множество точек (xмат.гр., yмат.гр.) на плоскости (точек, принадлежащих множеству R2), таких, что их координаты удовлетворяют равенствам

xмат.гр. = x,

yмат.гр. = f(xмат.гр.) = y = f(x).

При традиционном отображении графика функции на бумаге из-за невозможности нарисовать точку бесконечно малого размера происходит, во-первых, замена множества действительных чисел множеством рациональных (исходя из точности применяемых средств измерения), а во-вторых, представление каждой точки множеством точек, которое можно приближенно считать кругом с некоторым конечным диаметром, соответствующим минимальной толщине линии, оставляемой используемыми средствами рисо-вания (для самых распространенных в настоящее время – от 0,1 до 1 мм). При этом направление осей координат традиционно выбирается для оси OX слева направо, для оси OY – снизу вверх, а расположение точки (0, 0) выбирается исходя из вида функции. Расположение точки (1, 1), т.е. выбор единицы измерения или масштаба графика, определяется в зависимости от имеющихся средств измерения и требуемой точности графика. Очевидно, что на некотором листе бумаги фиксированного размера A мм по горизонтали (вдоль оси OX) на B мм по вертикали (вдоль оси OY) при условии, что значению x = 1 соответствует горизонтальная черта длиной MX, а значению y = 1 – вертикальная черта длиной MY мм, может быть полностью отображена лишь такая функция, область определения которой полностью находится внутри отрезка

[xmin, xmax], а область значений – внутри отрезка [ymin, ymax], таких что |xmax×MX xmin×MX| ≤ А и |ymax×MY ymin×MY| ≤ B. При этом MX и MY играют роль, во-первых, масштабных коэффициентов, а во-вторых – коэффициентов преобразования единиц измерения из абстрактных математических «единиц» в конкретные единицы измерения длины, в данном случае – в миллиметры. Поэтому коэффициенты MX и MY имеют размерность «единица длины/единицу» или, если считать «математическую единицу» безразмерной, то просто «единица длины», в данном случае – миллиметры. В случае если область определения и область значений функций полностью находятся внутри некоторых отрезков конечной длины, то график такой функции путем выбора соответствующих коэффициентов MX и MY всегда можно раз-местить на листе заданного размера A

на

B. Для максимально полного использования листа при вышеприведенных парамет-

рах

функции

коэффициенты

будут

вычисляться

по

формулам

MX = А/(|xmax – xmin|) и MY = B/(|ymax – ymin|). Разумеется, при этом возможно как искажение пропорций (различный масштаб по осям), так и просто существенное искажение вида функции – как правило,

из-за слияния соседних точек, связанного с физической невоз-можностью нарисовать точку не иначе как некоторое пятно вполне конечного размера. Если же область определения или область значений функции неограниченна, то физически отобразить можно только некоторый интересующий нас фрагмент графика, обозначив тем или иным способом продолжение изменения аргумента или значения за пределами отображенной части. Как правило, для этого используют либо некоторое продолжение графика после крайних явно обозначенных точек, либо изображение асимптот.

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

51

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

Например, рассмотренная библиотека SDL_draw, как и многие другие библиотеки отображения, предполагает, что верхний левый угол экрана (или окна, или конкретной поверхности отображения) имеет координаты (0, 0), а правый нижний – (width–1, height–1), где width – число доступных пикселей по ширине, а height – по высоте. Таким образом, ось OX направлена традиционно слева направо, а ось OY – сверху вниз. Сочетание этих двух факторов приводит к необходимости использовать явное округление и преобразование типов, а также явное указание экранных координат (x0экр, y0экр) в пикселях для точки (0, 0) на математической плоскости при вычислении экранных координат каждой точки графика. Также меняется и единица измерения коэффициентов MX и MY на «пиксели/единица» или «пиксели». Для обеспечения точности все округления следует производить только после того, как из мате-матических координат получено экранное (в пикселях) смещение отображаемой точки относительно положения на экране начала математических координат, и уже это смещение использовать для вычисления собственно экранных координат отображаемой точки. При ранее приведенных ограничениях на область определения и область значения функции, значениях ширины экрана width и высоты height пикселей, с приведенным выше направлением экранных осей координат потребуется вычислить следующие коэффициенты и экранные координаты точки начала координат для того, чтобы график функции полностью поместился на экране:

MX = width/(|xmax – xmin|) пикселей, MY = height/(|ymax – ymin|) пикселей, x0экр = floor(– xmin×MX) пикселей, y0экр = floor(height + ymin×MY) пикселей.

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

С использованием рассчитанных коэффициентов экранные координаты (xэкр, yэкр) каждой точки (x, y) на графике функции можно будет вычислить следующим образом:

xэкр = x0экр + floor(x×MX) пикселей, yэкр = y0экр – floor(ymin×MY) пикселей.

Поскольку график отображается на дискретном устройстве вывода, то очевидно, что имеет смысл рассчитывать и отображать некоторое минимальное количество точек, достаточное для восприятия полученного изображения как графика. В качестве ниж-ней границы числа точек можно рассмотреть width – «исполь-зование каждого пикселя». Тогда точки рассчитываются от xmin до xmax с шагом ∆x = (|xmax – xmin|)/width = MX-1. Однако при этом часто для точек непрерывной функции, xэкр которых различаются на единицу, координаты yэкр различаются на значительную величину, что на экране выглядит как разбросанные отдельные точки, не похожие на график.

Одним из способов устранения данного недостатка является увеличение числа рассчитываемых и отображаемых точек (когда для нескольких близко расположенных рассчитанных точек совпадают значения xэкр, а координаты yэкр различаются незначительно). Например, выбирается шаг

∆x = (|xmax – xmin|)/(10×width) или

∆x = (|xmax – xmin|)/(100×width) и т.п. Основной недостаток данного способа – существенное увеличение вычислительных затрат, а также пропорциональное увеличение числа относительно медлен-ных в графическом режиме операций ввода-вывода по отображе-нию большого числа соседних (часто совпадающих) точек. При этом некоторые функции, имеющие существенное изменение пове-дения (такие как экспонента, логарифм или гипербола), для обеспе-чения визуального восприятия могут требовать расчета до 100 и более точек между двумя соседними пикселями по горизонтали.

Альтернативой построению графиков функций по точкам является построение графика приближенной кусочно-линейной функции, представляющего собой ломаную линию, состоящую из отрезков, соединяющих рассчитанные точки исходной функции. При этом построение самих отрезков между точками осуществля-ется имеющимися средствами библиотек рисования изображений. Следует заметить, что, в силу дискретности устройств отображения, даже при поточечном рисовании графика также фактически получается график некоторой приближенной функции, зато про-изводительность второго способа существенно выше. Как правило, между точками, экранные координаты которых различаются по горизонтали на 1 пиксель, строится от 1 до 10 отрезков, поскольку дальнейшее увеличение их числа практически не будет влиять на восприятие графика.

52

Примеры программ построения графиков функций, написанные на языке С с использованием библиотеки SDL, приведены в приложении 3.

П Р И Л О Ж Е Н И Е 1

Примеры наложения поверхностей

Примеры демонстрируют возможные комбинации состояний флагов SDL_SRCCOLORKEY, SDL_SRCALPHA, значений полей format→Amask, format→colorkey и format→alpha

накладываемой и целевой поверхности и их влияние на результаты:

#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <SDL.h>

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;

53

}

/* После инициализации собственно 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,

54

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);

/* Создаем на поверхности равномерный белый фон

55

с зеленоватым оттенком: */ 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 <SN; 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);

56

else /* Принудительно сбрасываем флаг SDL_SRCALPHA */ SDL_SetAlpha(results[j][i], 0, 128);

}

}

}

}

/* Накладываем на results[i][j] все upper[i]

и выводим результаты: */ for(i = 0; i <SN; 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 <stdio.h> #include <stdlib.h> #include <math.h> #include <SDL.h> #include <SDL_ttf.h>

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

57

{

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;

58

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;

/* Обновление отображения измененной поверхности

59

на физическом устройстве вывода.

До этого вызова все операции на поверхности производятся в памяти. */

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);

60

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|), причем xmin = –32, xmax = 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 пикселей, */

61

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;x1<xmax;x1=x2, x2+=dx){

if((fabs(x1)-1e-4)>0 && (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 <stdio.h> #include <stdlib.h> #include <math.h> #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))

62

{

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;x1<xmax;x1=x2, x2+=dx){

if((fabs(x1)-1e-4)>0 && (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);

63

yscr2=y0scr-floor(y2*my); /*Отрезок красным цветом: */ Draw_Line(who_draw,xscr1,yscr1,

xscr2,yscr2,0xFF0000);

}

}

}

В качестве второго примера рассмотрим рисование графика функции y=a+b/(x*c+d) на отрезке [xmin; xmax] с использованием максимальной площади экрана. При этом все параметры вводятся пользователем с клавиатуры. Отображение осей координат, асимптот и т.п. не приводится.

#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #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());

64

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){

65

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;

66

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<width && 0<=yscr && yscr < height) 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;x1<xmax;x1=x2, x2+=dx){

if((fabs(x1)-1e-4)>0 && (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<width && 0<=yscr1 && yscr1 < height && 0<=xscr2 && xscr2<width && 0<=yscr2 && yscr2 < height) 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)

{

67

#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<WHOLE && !_fractional && !_ef)||

(_pointf && _fractional<FRACTIONAL && !_ef)|| (_ef && _exp<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 && !_fractional && !_ef) _whole=_whole+1;

else

if(_pointf && _fractional<FRACTIONAL && !_ef) _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

68

Соседние файлы в предмете Программирование