Changeset 65


Ignore:
Timestamp:
Jan 23, 2020, 12:21:53 AM (4 years ago)
Author:
chronos
Message:
  • Added: Separated TGame paint and state change events.
  • Modified: Animate tiles movements in background thread.
  • Modified: Initialize TCore as first application form.
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Forms/UFormMain.lfm

    r64 r65  
    5555  end
    5656  object TimerDraw: TTimer
    57     Interval = 20
     57    Interval = 10
    5858    OnTimer = TimerDrawTimer
    5959    left = 138
  • trunk/Forms/UFormMain.pas

    r64 r65  
    77uses
    88  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus, Math,
    9   ActnList, ExtCtrls, StdCtrls, UGame, UPersistentForm, UApplicationInfo;
     9  ActnList, ExtCtrls, StdCtrls, UGame, UPersistentForm, UApplicationInfo,
     10  LCLType, Syncobjs, DateUtils;
    1011
    1112type
     13  TFormMain = class;
     14
     15  { TMoveThread }
     16
     17  TMoveThread = class(TThread)
     18    FormMain: TFormMain;
     19    procedure Execute; override;
     20  end;
    1221
    1322  { TFormMain }
     
    3948    procedure FormShow(Sender: TObject);
    4049    procedure TimerDrawTimer(Sender: TObject);
     50    procedure EraseBackground(DC: HDC); override;
    4151  private
     52    DrawDuration: TDateTime;
    4253    MouseStart: TPoint;
    4354    MouseDown: Boolean;
    4455    RedrawPending: Boolean;
    4556    MoveBuffer: array of TMoveDirection;
     57    MoveBufferLock: TCriticalSection;
     58    MoveThread: TMoveThread;
    4659    procedure AddToMoveBuffer(Direction: TMoveDirection);
    4760    procedure ProcessMoveBuffer;
     
    6073uses
    6174  UCore;
     75
     76{ TMoveThread }
     77
     78procedure TMoveThread.Execute;
     79begin
     80  while not Terminated do begin
     81    FormMain.ProcessMoveBuffer;
     82    Sleep(10);
     83  end;
     84end;
    6285
    6386{ TFormMain }
     
    7295      40: AddToMoveBuffer(drDown);
    7396    end;
    74     ProcessMoveBuffer;
     97    //ProcessMoveBuffer;
    7598  end;
    7699end;
     
    111134      else if (Angle > 135) and (Angle <= 225) then AddToMoveBuffer(drLeft)
    112135      else if (Angle > 225) and (Angle <= 315) then AddToMoveBuffer(drUp);
    113       ProcessMoveBuffer;
     136      //ProcessMoveBuffer;
    114137    end;
    115138  end;
     
    123146
    124147procedure TFormMain.FormPaint(Sender: TObject);
    125 begin
     148var
     149  TimeStart: TDateTime;
     150begin
     151  TimeStart := Now;
    126152  Core.Game.Render(Canvas, Point(Width, Height - MainMenu1.Height));
     153  DrawDuration := Now - TimeStart;
    127154end;
    128155
     
    130157begin
    131158  Core.PersistentForm1.Save(Self);
     159  ControlStyle := [csOpaque];
    132160end;
    133161
    134162procedure TFormMain.FormCreate(Sender: TObject);
    135163begin
     164  MoveBufferLock := TCriticalSection.Create;
     165  MoveThread := TMoveThread.Create(True);
     166  MoveThread.FormMain := Self;
     167  MoveThread.FreeOnTerminate := False;
     168  MoveThread.Start;
    136169end;
    137170
    138171procedure TFormMain.FormDestroy(Sender: TObject);
    139172begin
     173  FreeAndNil(MoveThread);
     174  FreeAndNil(MoveBuffer);
    140175end;
    141176
     
    156191    RedrawPending := False;
    157192    Repaint;
    158   end;
     193    Caption := FloatToStr(Round(DrawDuration / OneMillisecond));
     194  end;
     195end;
     196
     197procedure TFormMain.EraseBackground(DC: HDC);
     198begin
     199  // Do nothing
    159200end;
    160201
    161202procedure TFormMain.AddToMoveBuffer(Direction: TMoveDirection);
    162203begin
    163   SetLength(MoveBuffer, Length(MoveBuffer) + 1);
    164   MoveBuffer[Length(MoveBuffer) - 1] := Direction;
     204  MoveBufferLock.Acquire;
     205  try
     206    SetLength(MoveBuffer, Length(MoveBuffer) + 1);
     207    MoveBuffer[Length(MoveBuffer) - 1] := Direction;
     208  finally
     209    MoveBufferLock.Release;
     210  end;
    165211end;
    166212
     
    168214begin
    169215  if not Core.Game.Moving then begin
     216    MoveBufferLock.Acquire;
    170217    while Length(MoveBuffer) > 0 do begin
     218      MoveBufferLock.Release;
    171219      Core.Game.MoveAllAndUpdate(MoveBuffer[0], True);
     220      MoveBufferLock.Acquire;
    172221      if Length(MoveBuffer) > 1 then
    173222        Move(MoveBuffer[1], MoveBuffer[0], (Length(MoveBuffer) - 1) * SizeOf(TMoveDirection));
     
    175224        SetLength(MoveBuffer, Length(MoveBuffer) - 1);
    176225    end;
    177   end else begin
     226    MoveBufferLock.Release;
    178227  end;
    179228end;
  • trunk/Game2048.lpr

    r54 r65  
    2929  Application.Scaled := True;
    3030  Application.Initialize;
     31  Application.CreateForm(TCore, Core);
    3132  Application.CreateForm(TFormMain, FormMain);
    32   Application.CreateForm(TCore, Core);
    3333  Application.Run;
    3434end.
  • trunk/UCore.pas

    r51 r65  
    4040  private
    4141    procedure GameChange(Sender: TObject);
     42    procedure GamePaint(Sender: TObject);
    4243    procedure GameWin(Sender: TObject);
    4344    procedure GameOver(Sender: TObject);
     
    8081  Game.Board.Size := Point(4, 4);
    8182  Game.OnChange := GameChange;
     83  Game.OnPaint := GamePaint;
    8284  Game.OnWin := GameWin;
    8385  Game.OnGameOver := GameOver;
     
    179181procedure TCore.GameChange(Sender: TObject);
    180182begin
    181   FormMain.Redraw;
    182183  UpdateInterface;
     184end;
     185
     186procedure TCore.GamePaint(Sender: TObject);
     187begin
     188  if Assigned(FormMain) then FormMain.Redraw;
    183189end;
    184190
  • trunk/UGame.pas

    r63 r65  
    104104    FOnChange: TNotifyEvent;
    105105    FOnGameOver: TNotifyEvent;
     106    FOnPaint: TNotifyEvent;
    106107    FOnWin: TNotifyEvent;
    107108    FRecordHistory: Boolean;
     
    115116    procedure SetScore(AValue: Integer);
    116117    procedure DoChange;
     118    procedure DoPaint;
    117119    procedure RenderTile(Canvas: TCanvas; Tile: TTile; TileRect: TRect; WithText: Boolean);
    118120    procedure GameOver;
     
    129131    TopScore: Integer;
    130132    AnimationDuration: Integer;
     133    AnimationTick: Integer;
    131134    WinTileValue: Integer;
    132135    UndoEnabled: Boolean;
     
    155158    property Running: Boolean read FRunning write FRunning;
    156159    property OnChange: TNotifyEvent read FOnChange write FOnChange;
     160    property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
    157161    property OnWin: TNotifyEvent read FOnWin write FOnWin;
    158162    property OnGameOver: TNotifyEvent read FOnGameOver write FOnGameOver;
     
    506510end;
    507511
     512procedure TGame.DoPaint;
     513begin
     514  if Assigned(FOnPaint) then FOnPaint(Self);
     515end;
     516
    508517procedure TGame.GameOver;
    509518begin
     
    516525  if FSkin = AValue then Exit;
    517526  FSkin := AValue;
    518   DoChange;
     527  DoPaint;
    519528end;
    520529
     
    595604  AnimateTiles;
    596605  DoChange;
     606  DoPaint;
    597607end;
    598608
     
    763773      Inc(P.Y, Area.Increment.Y);
    764774    end;
    765     DoChange;
     775    DoPaint;
    766776  end;
    767777  FMoving := False;
     
    945955              Trunc(Part * DirectionDiff[Direction].Y * 100));
    946956        end;
    947       DoChange;
    948       Application.ProcessMessages;
    949       Sleep(1);
     957      DoPaint;
     958      //Application.ProcessMessages;
     959      Sleep(AnimationTick);
    950960    until Time > EndTime;
    951961
     
    968978      Board.Tiles[Y, X].Value := Board.Tiles[Y, X].NewValue;
    969979    end;
    970   DoChange;
     980  DoPaint;
    971981  FMoving := False;
    972982end;
     
    10081018          Board.Tiles[Y, X].Shift := Point(Trunc(Part * 100), Trunc(Part * 100));
    10091019      end;
    1010     DoChange;
    1011     Application.ProcessMessages;
    1012     Sleep(1);
     1020    DoPaint;
     1021    //Application.ProcessMessages;
     1022    Sleep(AnimationTick);
    10131023  until Time > EndTime;
    10141024
     
    10191029        Board.Tiles[Y, X].Shift := Point(0, 0);
    10201030      end;
    1021   DoChange;
     1031  DoPaint;
    10221032  FMoving := False;
    10231033end;
     
    11551165  end;
    11561166  DoChange;
     1167  DoPaint;
    11571168end;
    11581169
     
    11601171begin
    11611172  AnimationDuration := 30;
     1173  AnimationTick := 10; // ms
    11621174  WinTileValue := 11; // 2^11 = 2048
    11631175  Board := TBoard.Create;
Note: See TracChangeset for help on using the changeset viewer.