Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[34.204.176.71] |
|
Сообщ.
#1
,
|
|
|
===========================
Это заготовка. Просто содрал с одного сайта, ну и немного добавил от себя. Будет наподобие уроков в одной теме. Зацените... =========================== - Графика - Graphics - Необходимые процедуры и функции для работы с графикой собраны стандартном модуле - Graph. Инициализация графики производится с помощью процедуры InitGraph, которая имеет вид: InitGraph(GraphDriver, GraphMode, Path); где переменные GraphDriver и GraphMode имеют тип Integer, а переменная Path имеет тип String. GraphDriver - целая переменная, определяющая тип графического драйвера (VGA,EGA,CGA,..) Большинство мониторов имеют тип VGA, и выше - SVGA(Super VGA),XGA... GraphMode задает режим работы графического адаптера. Для VGA это режимы VGALo,VGAMed и VGAHi. Допустим, программа находится в директории C:\TP7\MYPROG Path - путь к файлу-драйверу egavga.bgi Если он находится в той же директории, что и наша программа, то укажем Path='' Как правило, файл egavga.bgi находится в директории BGI, поэтому Path='..\BGI' В случае, если вы запускаете программу, неправильно указав путь к этому файлу, получите сообщение-ошибку о том, что графический режим не инициализирован. Чтобы автоматически определить тип графического драйвера, существует функция Detect, которая применяется так: GraphDriver:=Detect; Процедура CloseGraph заканчивает работу с графикой и переводит экран обратно в текстовый режим. Для работы с графикой нам надо дописать в разделе Uses модуль Graph. Пример. Uses Graph;{Подключение модуля библиотеки графических процедур} Var GraphDriver, GraphMode : integer; Begin GraphDriver := detect; {автоопределение типа драйвера } {Инициализация графического режима} InitGraph(GraphDriver, GraphMode, '..\BGI'); if GraphResult<>grOK { графический режим не установился } then halt; { прерываем программу } { Сюда мы будем добавлять процедуры рисования. В следующем примере... } Writeln('Press Enter'); readln; { нажать Ввод } СloseGraph; {Закрытие графического режима} End. Система координат в графическом режиме. Все пиксели считаются относительно левого верхнего угла экрана с координатами (0,0) Чтобы узнать максимальные координаты экрана в текущем режиме работы, воспользуемся стандартными функциями GetMaxX и GetMaxY. Итак, отсчет начинается с верхнего левого угла с координатами (0;0), значение Х - столбец, отсчет слева направо; значение Y - строка, отсчет сверху вниз. Чтобы строить изображение, нужно указать точку начала вывода. В графическом режиме нет видимого курсора, но есть так называемый невидимый текущий указатель (Current Pointer). После инициализации графического режима указатель стоит в точке (0;0). Чтобы переместить его в нужное место используют следующие процедуры: MoveTo (X, Y), где переменные X, Y типа Integer - перемещает текущий указатель в точку с координатами (X,Y). Например, MoveTo (200, 100) MoveRel (dX, dY), где переменные dX, dY типа Integer - перемещает текущий указатель по горизонтали на расстояние, равное dX пикселям, а по вертикали на расстояние, равное dY пикселям. (Relative (англ.) - относительно) Например, если после выполнения предыдущей процедуры текущий указатель находится в точке (200, 100), то после выполнения процедуры MoveRel (25, 150) он будет находится в точке с координатами (225, 250). Эта тема была разделена из темы "Неотёсанные топики" |
Сообщ.
#2
,
|
|
|
Пример применения GetImage и PutImage для анимации.
Принцип анимации: program GrCursor; uses CRT, Graph; procedure InitGraphics; Var grDriver, grMode : Integer; begin grDriver := Detect; InitGraph (grDriver, grMode, '..\bgi'); if GraphResult<>grOk then begin writeln ('Gr. Error!'); halt (1); end; end; Const Width = 20; Height = 20; Step = 20; var c: char; size,x,y,i: word; PCursor, PScreenBlock: pointer; cx, cy: integer; procedure MoveCursor (dx, dy: integer); begin PutImage (X, Y, PScreenBlock^, NormalPut); { восстановить предыдущий блок } { изменить координаты } inc (X, dx); inc (Y, dy); GetImage (X, Y, X+Width, Y+Height, PScreenBlock^); { сохранить текущий блок перед тем, как отрисовывать курсор } PutImage (X, Y, PCursor^, OrPut); { вставить новый блок } end; begin InitGraphics; if GraphResult <> grOk then exit; cx := GetMaxX div 2; cy := GetMaxY div 2; x := cx - Width div 2; y := cy - Height div 2; SetColor (LightBlue); Line (0, 0, Width, Height); Line (0, Height, Width, 0); Size := ImageSize (0, 0, Width, Height); { Вычисляем размер картинки, который будем резервировать } GetMem (PCursor, Size); { Резервируем память для курсора } GetMem (PScreenBlock, Size); { Резервируем память сохраняемого блока } GetImage (0, 0, Width, Height, PCursor^); { Сохранить курсор в память } ClearDevice; MoveCursor (0, 20); SetColor (Red); Line (0, 0, GetMaxX, GetMaxY); repeat c := readkey; if c=#0 then c := readkey; case c of #72: {Up} MoveCursor (0, -Step); #80: {Down} MoveCursor (0, Step); #75: {Left} MoveCursor (-Step, 0); #77: {Right} MoveCursor (Step, 0); end; until c=#27; { Освобождение памяти } FreeMem (PCursor, Size); FreeMem (PScreenBlock, Size); CloseGraph; end. Зацените. Что добавить или заменить? П.С. А это кому-то надо вообще? Добавлено Да, кстати: Процедура MoveCursor собственно, и выполняет анимацию. Передаваемые в неё параметры - это смещение dx,dy от предыдущего значения (x,y), то есть курсор переместится в точку (x+dx,y+dy). Step - шаг передвижения. Не забывайте, что точка отсчёта (0,0) находится в левом верхнем углу, и направление оси Y - вниз, а не вверх, как мы привыкли. Добавлено Желательно добавить проверку выхода курсора за границы экрана, но вы можете сделать это сами. Это сообщение было перенесено сюда или объединено из темы "Создаём Offline FAQ" |
Сообщ.
#3
,
|
|
|
Цитата Romtek @ Кто может составить статью по применению видеостраниц для анимации? Описать всё популярным языком. дык там три строчки var page:byte; ... while not (exit_event) do begin page:=1-page; {страницы нумеруются с нуля, этим оператором меняется 0 на 1, а 1 на 0} setactivepage(page); {теперь все рисование будет на спрятанной странице} process_required_events; {реагируем на кнопочки итп} draw_entire_page; {перерисовываем} setvisualpage(page); {показываем только что нарисованную страницу} time_wait; {обычно delay или работа с таймером, в это время созерцаем нарисованное} end; Это сообщение было перенесено сюда или объединено из темы "Создаём Offline FAQ" |
Сообщ.
#4
,
|
|
|
{ Rectangle rotation around the first point (c) Romtek, 2005 } {$G+,N+,E-} uses Graph, CRT; const N = 4; {vertices number} type TPoint = record {structure, that stores point coordinate} x, y: integer; end; TPoly = array [1..N] of TPoint; {all coordinates} var Rect: TPoly; x0, y0: integer; procedure InitGr; var gd, gm: integer; begin gd := VGA; gm := VGAHi; InitGraph (gd, gm, '..\bgi'); {Check if BGI driver is in the path} if GraphResult <> grOk then halt (1); end; procedure PlotRect; var i: integer; begin MoveTo (x0 + Rect[1].x, y0 - Rect[1].y); for i := 2 to N do with Rect[i] do LineTo (x0 + x, y0 - y); LineTo (x0 + Rect[1].x, y0 - Rect[1].y); end; procedure Rotate (phi: single); var xx, yy, i: integer; begin for i := 2 to N do with Rect[i] do begin xx := x; yy := y; x := Rect[1].x + Round ((xx-Rect[1].x) * cos(Phi) - (yy-Rect[1].y) * sin(Phi)); y := Rect[1].y + Round ((xx-Rect[1].x) * sin(Phi) + (yy-Rect[1].y) * cos(Phi)); end; end; var i: integer; begin Randomize; InitGr; x0 := GetMaxX div 2; y0 := GetMaxY div 2; for i := 1 to N do with Rect[i] do begin x := Random (x0) - (x0 div 2); y := Random (y0) - (y0 div 2); end; SetColor (Yellow); SetWriteMode(XORPut); {From help: Two successive XOR commands will erase the line and restore the screen to its original appearance.} PlotRect; readln; while not KeyPressed do begin PlotRect; {Erase old rectangle} Rotate (pi/6.0); {30 degrees} PlotRect; {Put new rectangle} delay (800); end; CloseGraph; end. Добавлено { Управление движением курсора с помощью стрелок (c) Vesper, Romtek } uses Graph, Crt; procedure InitGraphics; Const PathToBGI = 'e:\bp\bgi'; var gd, gm, ErrorCode: Integer; begin gd := VGA; gm := VGAHi; InitGraph (gd, gm, PathToBGI); ErrorCode := GraphResult; if ErrorCode <> grOk then begin Writeln ('Graphics error: ', GraphErrorMsg (ErrorCode)); Readln; Halt (1); end; end; Const Border = 5; var i, x, y, mx, my :integer; eexit:byte; c:char; procedure DrawCursor; begin line (x - 15, y, x - 1, y); line (x, y - 15, x, y - 1); line (x + 15, y, x + 1, y); line (x, y + 15, x, y + 1); end; begin eexit := 0; InitGraphics; mx := GetMaxX; my := GetMaxY; x := mx div 2; y := my div 2; OutText ('Press Esc to exit'); setcolor (Yellow); DrawCursor; repeat c := readkey; if c=#27 then eexit := 1; if c=#0 then begin c := readkey; setcolor (Black); DrawCursor; case c of 'K': begin dec (x, 5); if x <= Border then x := Border; end; 'M': begin inc (x, 5); if x >= mx - Border then x := mx - Border; end; 'H': begin dec (y, 5); if y <= Border then y := Border; end; 'P': begin inc (y, 5); if y >= my - Border then y := my - Border; end; end; setcolor (Yellow); DrawCursor; end; until eexit > 0; closegraph; end. |
Сообщ.
#5
,
|
|
|
Пример построения графика распределения случайных чисел (Random) с применением всех правил масштабирования.
Рассмотрим такое задание: Нарисовать график нормального распределения случайных чисел. Для этого определим сначала границы вывода графика в рамке, у которой отступ по горизонтали составляет XMargin процентов от общей ширины экрана (пикселей) и отступ по вертикали YMargin процентов. XMargin = 4; { % ширины экрана } YMargin = 20; { % высоты экрана } --------------- | ----------- | | | | | | | | | | | | | | ----------- | --------------- Xborder и Yborder - это количество пикселей между границей экрана и рамкой по горизонтали и вертикали, соответственно. Их вычисляем так: Xborder := GetMaxX div 100 * Xmargin; Yborder := GetMaxY div 100 * Ymargin; Xmin, Xmax - левая и правая границы рамки, Ymin, Ymax - верхняя и нижняя границы рамки. Эти параметры надо вычислить, исходя из данных Xborder и Yborder. Допустим, имеем такие параметры нормального распределения: MeanValue : single = 0.0; { мат.ожидание } StDev : single = 1.2; { среднеквадр.отклонение } Теперь надо задать диапазон значений по оси X и оси Y. По оси X мы ничем не ограничены, так как нет зависимости от х (генератор случайных чисел не имеет входного параметра), поэтому берём Xmin, Xmax. По оси Y надо задать нижнюю и верхнюю границу YminValue и YmaxValue, которые принимают максимальные значения генератора + оставить некоторый запас, чтобы график не выходил за пределы рамки: YmaxValue : single = 5.0; YminValue : single = -5.0; Начальное значение x будет Xmin, а конечное - Xmax. Разобьём этот промежуток на Parts частей: Parts = 8; Шаг между соседними значениями вычисляется тогда по формуле Xstep = Width / Parts Чтобы вывести график в пределах заданной границы рамки, нужно вычислить масштаб по горизонтали. Т.е. поделить высоту экрана на ширину диапазона принимаемых значений: Yscale = Height / (YmaxValue - YminValue) Введём точку отсчёта (Xorig , Yorig) ,относительно которой будет строиться график распределения. Тогда сгенерированное случайное число получает координаты (xs , ys) xs = Xorig + x ys = Yorig - NormRand (MeanValue, StDev) * Yscale Функция NormRand генерирует случайное число по закону нормального распределения с заданными параметрами MeanValue и StDev. К значению x прибавляем каждый раз шаг Xstep и таким образом рисуем график. (* Data visualization of Normal distribution. (c) 2005, Romtek *) {$N+} program Viz2; Uses Crt, Graph {, v256 , PCX16{}; Const Title = 'Data visualization of Normal distribution'; TitleColor = White; BorderColor = Cyan; MeanColor = Red; StDevColor = LightGray; LineColor = Magenta; NumColor = Yellow; XMargin = 4; { % ширины экрана } YMargin = 20; { % высоты экрана } MeanValue : single = 0.0; { мат.ожидание } StDev : single = 1.2; { среднеквадр.отклонение } YmaxValue : single = 5.0; YminValue : single = -5.0; Parts = 8; { Распределение по нормальному закону } function NormRand (Mx, S : single) : single; { Mx - мат.ожидание, S - среднеквадр.отклонение } var A,B,R,SQ : single; begin repeat A := 2.0 * Random - 1.0; B := 2.0 * Random - 1.0; R := Sqr(A) + Sqr(B) until (R < 1.0); SQ := Sqrt(-2.0 * Ln(R) / R); NormRand := Mx + S * A * SQ end; function f2s (f: single): String; { convert type single to string } var S: string[6]; begin Str(f : 3 : 2, S); f2S := S; end; procedure PlotGraph; var Xorig, Yorig, x, Xstep, Xmin, Xmax, Ymin, Ymax, Width, Height, Xborder, Yborder, xs, ys : integer; f, Yscale : single; procedure Init; { расчёт всех данных } begin Xborder := GetMaxX div 100 * Xmargin; Yborder := GetMaxY div 100 * Ymargin; Xmin := Xborder; Ymin := Yborder; Xmax := GetMaxX - Xborder; Ymax := GetMaxY - Yborder; { определение начала координат графика } Xorig := Xmin; Yorig := GetMaxY div 2; { определение высоты и ширины графика } Width := Xmax - Xmin; Height := Ymax - Ymin; { шаг между соседними значениями} Xstep := Width div Parts; Yscale := Height / (YmaxValue - YminValue); end; begin Init; { Вывести сообщение над графиком, по центру } SetColor (TitleColor); OutTextXY ( (GetMaxX - TextWidth (Title)) div 2, (Ymin - TextHeight (Title)) div 2, Title); { граница поля графика } SetColor (BorderColor); Rectangle (Xmin, Ymin, Xmax, Ymax); { Линия мат. ожидания } SetColor (MeanColor); ys:= Yorig - round (MeanValue * Yscale); Line (Xmin, ys, Xmax, ys); { Линии станд. отклонения } SetColor (StDevColor); SetLineStyle(DottedLn, 0, NormWidth); ys := Yorig - round ((MeanValue - StDev) * Yscale); Line (Xmin, ys, Xmax, ys); ys := Yorig - round ((MeanValue + StDev) * Yscale); Line (Xmin, ys, Xmax, ys); { сам график } SetLineStyle(SolidLn, 0, NormWidth); x := 0; while x <= (Xmax - Xmin) do begin SetColor (LineColor); xs := Xorig + x; f := NormRand (MeanValue, StDev); ys := Yorig - round (f * Yscale); if x = 0 then MoveTo (xs, ys); { для первой точки установим графический курсор } LineTo (xs, ys); { и будем рисовать линию от него до заданной точки. После каждого вызова этой функции гр. курсор поменяет позицию на указанную в параметрах } SetColor (NumColor); OutTextXY (xs, ys, f2s (f)); { выводим значения случайных чисел } x := x + Xstep; { прибавляем каждый раз шаг Xstep } end; end; var Gd,Gm: Integer; begin Gd := Vga; gm := VgaHi; InitGraph(Gd,Gm,'..\..\bgi'); { SetVMode (v640x400);} if GraphResult <> grOk then Halt (1); Randomize; PlotGraph; readLn; { Save_PCX16('viz2.pcx');{} CloseGraph; end. График нормального распределения (скриншот): Прикреплённая картинка
|
Сообщ.
#6
,
|
|
|
Зацените, плиз.
Хочу услышать комментарии к этой программе. |