Changeset 9


Ignore:
Timestamp:
Sep 26, 2019, 11:29:03 PM (5 years ago)
Author:
chronos
Message:
  • Added: Cell move animation.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UGame.pas

    r6 r9  
    66
    77uses
    8   Classes, SysUtils, Dialogs, fgl, Graphics, Types;
     8  Classes, SysUtils, Dialogs, fgl, Graphics, Types, Forms, Math;
    99
    1010type
     
    1414  TCell = class
    1515    Value: Integer;
     16    NewValue: Integer;
    1617    Merged: Boolean;
     18    Moving: Boolean;
     19    Shift: TPoint;
    1720    procedure Assign(Source: TCell);
    1821  end;
     
    204207  ValueStr: string;
    205208  Frame: TRect;
     209  CellRect: TRect;
    206210  TextSize: TSize;
    207211  TopBarHeight: Integer;
     212  CellMargin: Integer;
    208213begin
    209214  TopBarHeight := ScaleY(24, 96);
     215  CellMargin := ScaleX(4, 96);
    210216  Canvas.Brush.Style := bsSolid;
    211217  Canvas.Brush.Color := clBlack;
     
    228234    Frame.Top + Frame.Height div 2 + (Size.Y * CellSize.Y) div 2);
    229235
     236  {  for Y := 0 to Size.Y - 1 do begin
     237    Canvas.MoveTo(Frame.Left, Frame.Top + Y * CellSize.Y);
     238    Canvas.LineTo(Frame.Left + Size.X * CellSize.X, Frame.Top + Y * CellSize.Y);
     239  end;
     240  for X := 0 to Size.X - 1 do begin
     241    Canvas.MoveTo(Frame.Left + X * CellSize.X, Frame.Top);
     242    Canvas.LineTo(Frame.Left + X * CellSize.X, Frame.Top + Size.Y * CellSize.Y);
     243  end;
     244  }
     245  Canvas.Brush.Style := bsSolid;
     246  Canvas.Brush.Color := clGray;
     247  Canvas.FillRect(Frame);
     248
    230249  Canvas.Font.Color := clBlack;
     250  // Draw static cells
    231251  for Y := 0 to Size.Y - 1 do
    232252    for X := 0 to Size.X - 1 do begin
    233       Canvas.Brush.Color := GetCellColor(Cells[Y, X].Value);
     253      if Cells[Y, X].Moving then Canvas.Brush.Color := GetCellColor(0)
     254        else Canvas.Brush.Color := GetCellColor(Cells[Y, X].Value);
    234255      Canvas.Brush.Style := bsSolid;
    235       Canvas.FillRect(Rect(Frame.Left + X * CellSize.X, Frame.Top + Y * CellSize.Y,
    236         Frame.Left + (X + 1) * CellSize.X, Frame.Top + (Y + 1) * CellSize.Y));
    237       if Cells[Y, X].Value <> 0 then begin
     256      CellRect := Bounds(
     257        Frame.Left + X * CellSize.X + CellMargin,
     258        Frame.Top + Y * CellSize.Y + CellMargin,
     259        CellSize.X - 2 * CellMargin, CellSize.Y - 2 * CellMargin);
     260      Canvas.FillRect(CellRect);
     261      if (Cells[Y, X].Value <> 0) and not Cells[Y, X].Moving then begin
    238262        ValueStr := IntToStr(Cells[Y, X].Value);
    239263        Canvas.Brush.Style := bsClear;
     
    243267          Canvas.Font.Height := Trunc(Canvas.Font.Height / TextSize.Width * CellSize.X);
    244268        TextSize := Canvas.TextExtent(ValueStr);
    245         Canvas.TextOut(Frame.Left + X * CellSize.X + CellSize.X div 2 -
     269        Canvas.TextOut(CellRect.Left + CellSize.X div 2 -
    246270          TextSize.Width div 2,
    247           Frame.Top + Y * CellSize.Y + CellSize.Y div 2 - TextSize.Height div 2, ValueStr);
     271          CellRect.Top + CellSize.Y div 2 - TextSize.Height div 2, ValueStr);
    248272      end;
    249273    end;
    250274
    251   for Y := 0 to Size.Y - 1 do begin
    252     Canvas.MoveTo(Frame.Left, Frame.Top + Y * CellSize.Y);
    253     Canvas.LineTo(Frame.Left + Size.X * CellSize.X, Frame.Top + Y * CellSize.Y);
    254   end;
    255   for X := 0 to Size.X - 1 do begin
    256     Canvas.MoveTo(Frame.Left + X * CellSize.X, Frame.Top);
    257     Canvas.LineTo(Frame.Left + X * CellSize.X, Frame.Top + Size.Y * CellSize.Y);
    258   end;
    259   Canvas.Brush.Style := bsClear;
    260   Canvas.Rectangle(Frame);
     275  // Draw moving cells
     276  for Y := 0 to Size.Y - 1 do
     277    for X := 0 to Size.X - 1 do
     278    if Cells[Y, X].Moving then begin
     279      Canvas.Brush.Color := GetCellColor(Cells[Y, X].Value);
     280      Canvas.Brush.Style := bsSolid;
     281      CellRect := Bounds(
     282        Frame.Left + X * CellSize.X + Trunc(Cells[Y, X].Shift.X / 100 * CellSize.X + CellMargin),
     283        Frame.Top + Y * CellSize.Y + Trunc(Cells[Y, X].Shift.Y / 100 * CellSize.Y + CellMargin),
     284        CellSize.X - 2 * CellMargin, CellSize.Y - 2 * CellMargin);
     285      Canvas.FillRect(CellRect);
     286      if Cells[Y, X].Value <> 0 then begin
     287        ValueStr := IntToStr(Cells[Y, X].Value);
     288        Canvas.Brush.Style := bsClear;
     289        Canvas.Font.Height := Trunc(CellSize.Y * 0.7); // * (CellSize.X * 0.7) / Canvas.TextWidth(ValueStr));
     290        TextSize := Canvas.TextExtent(ValueStr);
     291        if TextSize.Width > CellRect.Width then
     292          Canvas.Font.Height := Trunc(Canvas.Font.Height / TextSize.Width * CellSize.X);
     293        TextSize := Canvas.TextExtent(ValueStr);
     294        Canvas.TextOut(CellRect.Left + CellRect.Width div 2 -
     295          TextSize.Width div 2,
     296          CellRect.Top + CellRect.Height div 2 - TextSize.Height div 2, ValueStr);
     297      end;
     298    end;
    261299end;
    262300
     
    266304  AreaSize: TPoint;
    267305  Increment: TPoint;
     306  MoveDirection: TPoint;
    268307  P: TPoint;
    269   PN: TPoint;
     308  PNew: TPoint;
    270309  PI: TPoint;
    271310  MovedCount: Integer;
     311  X, Y: Integer;
     312  Step: Integer;
     313  I: Integer;
     314const
     315  StepCount = 10;
     316  AnimationDuration = 30;
    272317begin
    273318  //Diff := DirectionDiff[Direction];
     
    277322      AreaSize := Point(Size.X - 2, Size.Y - 1);
    278323      Increment := Point(1, 1);
     324      MoveDirection := Point(-1, 0);
    279325    end;
    280326    drUp: begin
     
    282328      AreaSize := Point(Size.X - 1, Size.Y - 2);
    283329      Increment := Point(1, 1);
     330      MoveDirection := Point(0, -1);
    284331    end;
    285332    drRight: begin
     
    287334      AreaSize := Point(Size.X - 2, Size.Y - 1);
    288335      Increment := Point(-1, 1);
     336      MoveDirection := Point(1, 0);
    289337    end;
    290338    drDown: begin
     
    292340      AreaSize := Point(Size.X - 1, Size.Y - 2);
    293341      Increment := Point(1, -1);
    294     end;
    295   end;
     342      MoveDirection := Point(0, 1);
     343    end;
     344  end;
     345  MovedCount := 0;
    296346  ClearMerged;
    297   MovedCount := 0;
    298   PI.Y := 0;
    299   while PI.Y <= AreaSize.Y do begin
    300     PI.X := 0;
    301     while PI.X <= AreaSize.X do begin
    302       P := Point(StartPoint.X + PI.X * Increment.X, StartPoint.Y + PI.Y * Increment.Y);
    303       PN.X := P.X + DirectionDiff[Direction].X;
    304       PN.Y := P.Y + DirectionDiff[Direction].Y;
    305       while IsValidPos(PN) do begin
    306         if (Cells[P.Y, P.X].Value <> 0) then begin
    307           if (Cells[PN.Y, PN.X].Value = 0) then begin
    308             MoveCell(Cells[P.Y, P.X], Cells[PN.Y, PN.X]);
    309             Inc(MovedCount);
    310           end else
    311           if (not Cells[P.Y, P.X].Merged) and (not Cells[PN.Y, PN.X].Merged) and
    312           (Cells[PN.Y, PN.X].Value = Cells[P.Y, P.X].Value) then begin
    313             Cells[PN.Y, PN.X].Value := Cells[PN.Y, PN.X].Value + Cells[P.Y, P.X].Value;
    314             Cells[PN.Y, PN.X].Merged := True;
    315             Cells[P.Y, P.X].Value := 0;
    316             Cells[P.Y, P.X].Merged := False;
    317             Inc(MovedCount);
     347  for I := 0 to Max(Size.X, Size.Y) - 1 do begin
     348    PI.Y := 0;
     349    for Y := 0 to Size.Y - 1 do
     350      for X := 0 to Size.X - 1 do begin
     351        Cells[Y, X].NewValue := Cells[Y, X].Value;
     352        Cells[Y, X].Moving := False;
     353      end;
     354
     355    while PI.Y <= AreaSize.Y do begin
     356      PI.X := 0;
     357      while PI.X <= AreaSize.X do begin
     358        P := Point(StartPoint.X + PI.X * Increment.X, StartPoint.Y + PI.Y * Increment.Y);
     359        PNew.X := P.X + DirectionDiff[Direction].X;
     360        PNew.Y := P.Y + DirectionDiff[Direction].Y;
     361        if IsValidPos(PNew) then begin
     362          if (Cells[P.Y, P.X].NewValue <> 0) then begin
     363            if (Cells[PNew.Y, PNew.X].NewValue = 0) then begin
     364              Cells[P.Y, P.X].Moving := True;
     365              Cells[PNew.Y, PNew.X].NewValue := Cells[P.Y, P.X].NewValue;
     366              Cells[PNew.Y, PNew.X].Merged := Cells[P.Y, P.X].Merged;
     367              Cells[P.Y, P.X].NewValue := 0;
     368              Cells[P.Y, P.X].Merged := False;
     369              Inc(MovedCount);
     370            end else
     371            if (not Cells[P.Y, P.X].Merged) and (not Cells[PNew.Y, PNew.X].Merged) and
     372            (Cells[PNew.Y, PNew.X].NewValue = Cells[P.Y, P.X].NewValue) then begin
     373              Cells[P.Y, P.X].Moving := True;
     374              Cells[PNew.Y, PNew.X].NewValue := Cells[PNew.Y, PNew.X].NewValue + Cells[P.Y, P.X].NewValue;
     375              Cells[PNew.Y, PNew.X].Merged := True;
     376              Cells[P.Y, P.X].NewValue := 0;
     377              Cells[P.Y, P.X].Merged := False;
     378              Inc(MovedCount);
     379            end;
    318380          end;
     381          P.X := PNew.X;
     382          P.Y := PNew.Y;
     383          PNew.X := P.X + DirectionDiff[Direction].X;
     384          PNew.Y := P.Y + DirectionDiff[Direction].Y;
    319385        end;
    320         P.X := PN.X;
    321         P.Y := PN.Y;
    322         PN.X := P.X + DirectionDiff[Direction].X;
    323         PN.Y := P.Y + DirectionDiff[Direction].Y;
     386        Inc(PI.X);
    324387      end;
    325       Inc(PI.X);
    326     end;
    327     Inc(PI.Y);
    328   end;
    329   DoChange;
     388      Inc(PI.Y);
     389    end;
     390    for Step := 0 to StepCount - 2 do begin
     391      for Y := 0 to Size.Y - 1 do
     392        for X := 0 to Size.X - 1 do begin
     393          if Cells[Y, X].Moving then
     394            Cells[Y, X].Shift := Point(Trunc(Step / StepCount * MoveDirection.X * 100),
     395              Trunc(Step / StepCount * MoveDirection.Y * 100));
     396        end;
     397      DoChange;
     398      Application.ProcessMessages;
     399      Sleep(AnimationDuration div StepCount);
     400    end;
     401    for Y := 0 to Size.Y - 1 do
     402      for X := 0 to Size.X - 1 do begin
     403        Cells[Y, X].Value := Cells[Y, X].NewValue;
     404        Cells[Y, X].Shift := Point(0, 0);
     405      end;
     406    DoChange;
     407  end;
    330408  Result := MovedCount;
    331409end;
Note: See TracChangeset for help on using the changeset viewer.