Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Живая открытка

Автор: Матвеев Игорь


- Я не покупаю кота в мешке,- сказал жених родителям невесты.
- До свадьбы я хотел бы увидеть свою нареченную в натуральном виде, какой ее бог сотворил!
Родители невесты долго колебались, но в конце концов согласились.
Жених очень внимательно осмотрел невесту и наконец сказал:
- Я не могу на ней жениться. У нее слишком большие уши.

 Сегодня я решил сделать нечто вроде открытки, живой открытки - изображение будет как бы колеблющемся.

 Сперва необходимо решить, что будет изображено на открытке, я решил изобразить сердце, а под ним надпись вроде "Я люблю тебя". Хотя рисовать можно все что угодно: зеленую новогоднюю елочку, симпатичную рожицу или даже цветок. Это не столь важно, смысл в том, что необходимо простое векторное изображение - некоторое количество точек, определенным образом связанных между собой.

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

 Для исключения мигания, сначала изображение открытки рисуется на виртуальном Bitmap-е, а затем методом Draw() выводится на канву PaintBox-а.

 Код осветления изображения необходимо поместить в обработчике OnTimer таймера с минимальным интервалом. Поскольку работа с канвой занимает много времени, будем работать напрямую с Bitmap-ом через свойство ScanLine. В следующем коде представлен алгоритм осветления изображения:

type
  TRGB = record
    b, g, r: byte;
  end;
  ARGB = array[0..1] of TRGB;
  PARGB = ^ARGB;
var
  p    : PARGB;
  x, y : Integer;
begin
 for y := 0 to BMP.height - 1 do
  begin
    p := BMP.ScanLine[y];
    for x := 0 to BMP.width - 1 do
      begin
        if p[x].r <> 255 then p[x].r := p[x].r+2;
        if p[x].g <> 255 then p[x].g := p[x].g+2;
        if p[x].b <> 255 then p[x].b := p[x].b+2;
      end;
  end;

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

type
 THeart = record
   P1, P2, P3, P4 : TPoint; // Точки построения
   Top : Integer;           // Верхняя граница
   end;

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

function InitHeart(Rect : TRect): THeart;
begin
 with Result do
   begin
     // Сохраняем верхнюю грань сердца
     Top := Rect.Top;

     // Вычисление координат точек для построения
     P1.X := Rect.Left;
     P1.Y := Round(Rect.Top + (Rect.Bottom - Rect.Top) / 3);

     P2.X := Round((Rect.Left + Rect.Right) / 2);
     P2.Y := Round(Rect.Top + (Rect.Bottom - Rect.Top) / 9);

     P3.X := Rect.Right;
     P3.Y := P1.Y;

     P4.X := P2.X;
     P4.Y := Rect.Bottom;
   end;
end;

 Далее необходимо создать процедуру отрисовки сердца: сперва рисуются прямые линии, затем две дуги эллипса:

procedure DrawHeart(Canvas: TCanvas; Heart: THeart);
begin
 with Heart do
   begin
     Canvas.Pen.Color := HColor;

     Canvas.MoveTo(P1.X, P1.Y);
     Canvas.LineTo(P4.X, P4.Y);  
     Canvas.LineTo(P3.X, P3.Y);  

     Canvas.Arc(P1.X-3, Top, Round(P1.X+P3.X/2)+12, Round(Top+P4.Y/2), P2.X-7, P2.Y, P1.X, P1.Y+1);
     Canvas.Arc(P2.X-20, Top, P3.X+3, Round(Top+P4.Y/2), P3.X, P3.Y, P2.X-20, P2.Y+10);
   end;
end;

 Итак, поскольку сердце будет колеблющемся, необходимо две переменные типа THeart - первая (MHeart) будет хранить первоначальные координаты точек, вторая (NewHeart) непосредственно будет использоваться для рисования, координаты точек этого сердца будут вычисляться на основе координат первого с небольшим случайным "люфтом". В результате в OnCreate формы необходимо поместить следующий код:

 // Инициализация генератора случайных чисел
 Randomize;
 // Создание виртуального изображения
 BMP := TBitmap.Create;
 BMP.pixelformat := pf24bit;
 BMP.Width := Pole.Width;
 BMP.Height := Pole.Height;
 BMP.Canvas.Pen.Color := clRed;
 BMP.Canvas.Pen.Width := 3;
 // Вычисление первоночальных точек для построения сердца
 MHeart   := InitHeart(Rect(20, 5, Pole.Width - 20, Pole.Height - 80));
 NewHeart := MHeart;

 Рисование сердца тоже выносим в отдельный таймер с минимальным интервалом. Вот как это происходит:

 NewHeart.P1.X := MHeart.P1.X + Random(31) - 15;
 NewHeart.P1.Y := MHeart.P1.Y + Random(31) - 15;

 NewHeart.P2.X := MHeart.P2.X + Random(31) - 15;
 NewHeart.P2.Y := MHeart.P2.Y + Random(31) - 15;

 NewHeart.P3.X := MHeart.P3.X + Random(31) - 15;
 NewHeart.P3.Y := MHeart.P3.Y + Random(31) - 15;

 NewHeart.P4.X := MHeart.P4.X + Random(31) - 15;
 NewHeart.P4.Y := MHeart.P4.Y + Random(31) - 15;

 DrawHeart(BMP.Canvas, NewHeart);

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

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

Проект Delphi World © Выпуск 2002 - 2024
Автор проекта: USU Software
Вы можете выкупить этот проект.