heart animation

I recreated the heart scene from the Chinese drama 'Lighter and Princess' ep5 as a C language assignment using chatGPT and lazarus.

Drama Information : https://so.youku.tv/search_video/q_Lighter%20and%20Princess?searchfrom=1

1. compiler tool : Lazarus  ( Lazarus Homepage )

2. UI Design

3. source code

unit HeartAnimation;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Graphics, Controls, Forms, ExtCtrls, Math, Dialogs;

type
  TMyPoint = record
    X, Y: Double;
    Color: TColor;
  end;

  { TForm1 }
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { private declarations }
    const
      xScreen = 1200;
      yScreen = 800;
      PI = 3.14159265359;
      e = 2.71828;
      averag_distance = 0.162;
      quantity = 506;
      circles = 210;
      frames = 20;
    var
      origin_points: array of TMyPoint;
      points: array of TMyPoint;
      images: array of TBitmap;
      currentFrame: Integer;
      extend: Boolean;
      colors: array[0..6] of TColor;
    procedure CreateData;
    function ScreenX(x: Double): Double;
    function ScreenY(y: Double): Double;
    function CreateRandom(x1, x2: Integer): Integer;
    procedure UpdateFrame;
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  ClientWidth := xScreen;
  ClientHeight := yScreen;
  DoubleBuffered := True;

  SetLength(origin_points, quantity);
  SetLength(points, circles * quantity);
  SetLength(images, frames);

  colors[0] := RGBToColor(255, Min(32 + 204, 255), 83);
  colors[1] := RGBToColor(252, Min(222 + 204, 255), 250);
  colors[2] := RGBToColor(255, Min(0 + 153, 255), Min(0 + 204, 255));
  colors[3] := RGBToColor(255, Min(0 + 153, 255), Min(0 + 204, 255));
  colors[4] := RGBToColor(255, 2, Min(2 + 204, 255));
  colors[5] := RGBToColor(255, Min(0 + 153, 255), Min(8 + 204, 255));
  colors[6] := RGBToColor(255, 5, Min(5 + 204, 255));

  Randomize;  // Random number generator initialization

  CreateData;

  Timer1.Interval := 20;
  Timer1.Enabled := True;
end;

procedure TForm1.CreateData;
var
  index: Integer;
  x, y, x1, y1, x2, y2, radian, size, success_p, distance, distance_increase, x_increase, y_increase: Double;
  i, frame: Integer;
  bmp: TBitmap;
begin
  index := 0;
  x1 := 0;
  y1 := 0;

  radian := 0.1;
  while radian <= 2 * PI do
  begin
    x2 := 16 * Power(Sin(radian), 3);
    y2 := 13 * Cos(radian) - 5 * Cos(2 * radian) - 2 * Cos(3 * radian) - Cos(4 * radian);
    distance := Sqrt(Power(x2 - x1, 2) + Power(y2 - y1, 2));

    if distance > averag_distance then
    begin
      x1 := x2;
      y1 := y2;
      origin_points[index].X := x2;
      origin_points[index].Y := y2;
      Inc(index);
    end;

    radian := radian + 0.005;// 0.1;
  end;

  index := 0;
  size := 0.1;
  while size <= 20 do
  begin
    success_p := 1 / (1 + Power(e, 8 - size / 2));

    for i := 0 to quantity - 1 do
    begin
      if success_p > CreateRandom(0, 100) / 100.0 then
      begin
        points[index].Color := colors[CreateRandom(0, 6)]; // 0~6 index randeom choice
        points[index].X := size * origin_points[i].X + CreateRandom(-4, 4);
        points[index].Y := size * origin_points[i].Y + CreateRandom(-4, 4);
        Inc(index);
      end;
    end;

    size := size + 0.1;
  end;

  for frame := 0 to frames - 1 do
  begin
    bmp := TBitmap.Create;
    bmp.SetSize(xScreen, yScreen);
    bmp.Canvas.Brush.Color := clBlack;
    bmp.Canvas.FillRect(0, 0, xScreen, yScreen);

    for i := 0 to index - 1 do
    begin
      x := points[i].X;
      y := points[i].Y;
      distance := Sqrt(Power(x, 2) + Power(y, 2));

      if distance <> 0 then
      begin
        distance_increase := -0.0009 * distance * distance + 0.35714 * distance + 5;
        x_increase := distance_increase * x / distance / frames;
        y_increase := distance_increase * y / distance / frames;

        points[i].X := points[i].X + x_increase;
        points[i].Y := points[i].Y + y_increase;
      end;

      bmp.Canvas.Brush.Color := points[i].Color;
      bmp.Canvas.FillRect(Round(ScreenX(points[i].X)), Round(ScreenY(points[i].Y)), Round(ScreenX(points[i].X)) + 1, Round(ScreenY(points[i].Y)) + 1);
    end;

    size := 17;
    while size <= 23 do
    begin
      for i := 0 to quantity - 1 do
      begin
        if ((CreateRandom(0, 100) / 100.0 > 0.6) and (size >= 20)) or
           ((size < 20) and (CreateRandom(0, 100) / 100.0 > 0.95)) then
        begin
          if size >= 20 then
          begin
            x := origin_points[i].X * size + CreateRandom(-frame * frame div 5 - 15, frame * frame div 5 + 15);
            y := origin_points[i].Y * size + CreateRandom(-frame * frame div 5 - 15, frame * frame div 5 + 15);
          end
          else
          begin
            x := origin_points[i].X * size + CreateRandom(-5, 5);
            y := origin_points[i].Y * size + CreateRandom(-5, 5);
          end;

          bmp.Canvas.Brush.Color := colors[CreateRandom(0, 6)]; // 0~6 index randeom choice
          bmp.Canvas.FillRect(Round(ScreenX(x)), Round(ScreenY(y)), Round(ScreenX(x)) + 1, Round(ScreenY(y)) + 1);
        end;
      end;

      size := size + 0.3; // 0.1;
    end;

    images[frame] := bmp;
  end;
end;

function TForm1.ScreenX(x: Double): Double;
begin
  Result := x + xScreen / 2;
end;

function TForm1.ScreenY(y: Double): Double;
begin
  Result := -y + yScreen / 2;
end;

function TForm1.CreateRandom(x1, x2: Integer): Integer;
begin
  Result := Random(x2 - x1 + 1) + x1;
end;

procedure TForm1.UpdateFrame;
begin
  if extend then
  begin
    if currentFrame = frames - 1 then
      extend := False
    else
      Inc(currentFrame);
  end
  else
  begin
    if currentFrame = 0 then
      extend := True
    else
      Dec(currentFrame);
  end;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  Canvas.Draw(0, 0, images[currentFrame]);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  UpdateFrame;
  Invalidate;
end;

end.

4. Screen Capture

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值