{******************************************************************************}
{* Иллюстрация к книге "DirectX. Графика в проектах Delphi".                  *}
{* Издательство BHV. www.bhv.ru                                               *}
{* Краснов М.В. softgl@chat.ru                                                *}
{******************************************************************************}
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  AppEvnts, ExtCtrls,
  DirectDraw, DDUtil,
  CDXScreenX, CDXTileX, CDXMapX, CDXInputX, DirectInput;

type
  TfrmDD = class(TForm)
    ApplicationEvents1: TApplicationEvents;
    procedure FormCreate(Sender: TObject);
    procedure ApplicationEvents1Deactivate(Sender: TObject);
    procedure ApplicationEvents1Restore(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
    procedure FormActivate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FActive : BOOL;
    function UpdateFrame : HRESULT;
  public
    { Public declarations }
  protected
    procedure FormSetCursor(var aMsg : TMessage); message WM_SETCURSOR;
  end;

const
  ScreenWidth    = 640;
  ScreenHeight   = 480;
  ScreenBitDepth = 8;

var
  frmDD : TfrmDD;
  GameInput : CDXInput;
  GameScreen : CDXScreen;
  LandScape : CDXTile;
  Map1 : CDXMap;
  Map2 : CDXMap;
  Map3 : CDXMap;
  Map4 : CDXMap;
  MapScrollSpeed : Integer = 4;

implementation

{$R *.DFM}

procedure TfrmDD.FormCreate(Sender: TObject);
begin
  GameInput := CDXInput.CreateCDXInput;
  GameInput.Create(HInstance, Handle);
  GameScreen := CDXScreen.CreateCDXScreenCustomBPP(Handle, ScreenWidth,
                ScreenHeight, ScreenBitDepth);
  GameScreen.LoadPalette('Anim.bmp');
  LandScape := CDXTile.CDXTileCustom(GameScreen,'Anim.bmp',64, 64, 4);

  Map1 := CDXMap.CDXMap(LandScape, GameScreen);
  Map1.CreateMap(64, 64, 1);

  Map2 := CDXMap.CDXMap(LandScape, GameScreen);
  Map2.CreateMap(64, 64, 2);

  Map3 := CDXMap.CDXMap(LandScape, GameScreen);
  Map3.CreateMap(64, 64, 3);

  Map4 := CDXMap.CDXMap(LandScape, GameScreen);
  Map4.CreateMap(64, 64, 4);
end;

procedure TfrmDD.ApplicationEvents1Deactivate(Sender: TObject);
begin
  FActive := False;
  Application.Minimize;
end;

procedure TfrmDD.FormSetCursor(var aMsg : TMessage);
begin
  SetCursor(0);
end;

procedure TfrmDD.ApplicationEvents1Restore(Sender: TObject);
begin
  WindowState := wsMaximized;
  FActive := True;
end;

function KeyDown (Key : Byte): BOOL;
begin
  Result := GameInput.Keys[Key] = 128;
end;

procedure UpdateKeys;
begin
  if KeyDown(DIK_RIGHT) then begin
     Map1.WrapScrollRight(MapScrollSpeed);
     Map2.WrapScrollRight(MapScrollSpeed);
     Map3.WrapScrollRight(MapScrollSpeed);
     Map4.WrapScrollRight(MapScrollSpeed);
  end;
  if KeyDown(DIK_LEFT) then begin
     Map1.WrapScrollLeft(MapScrollSpeed);
     Map2.WrapScrollLeft(MapScrollSpeed);
     Map3.WrapScrollLeft(MapScrollSpeed);
     Map4.WrapScrollLeft(MapScrollSpeed);
  end;
  if KeyDown(DIK_UP) then begin
     Map1.WrapScrollUp(MapScrollSpeed);
     Map2.WrapScrollUp(MapScrollSpeed);
     Map3.WrapScrollUp(MapScrollSpeed);
     Map4.WrapScrollUp(MapScrollSpeed);
  end;
  if KeyDown(DIK_DOWN) then begin
     Map1.WrapScrollDown(MapScrollSpeed);
     Map2.WrapScrollDown(MapScrollSpeed);
     Map3.WrapScrollDown(MapScrollSpeed);
     Map4.WrapScrollDown(MapScrollSpeed);
  end;
  if KeyDown(DIK_ESCAPE) then begin
     GameScreen.FadeTo(255, 255, 255, 0);
     GameScreen.FadeOut(4);
     frmDD.Close;
  end;
end;

function TfrmDD.UpdateFrame : HRESULT;
var
  Window1 : TRECT;
  Window2 : TRECT;
  Window3 : TRECT;
  Window4 : TRECT;
begin
  SetRect (Window1, 0, 0, 320, 240);
  SetRect (Window2, 320, 0, 640, 240);
  SetRect (Window3, 0, 240, 640, 480);
  SetRect (Window4, 320, 240, 640, 480);

  GameInput.Update;
  UpdateKeys;

  Map1.DrawClipped(GameScreen.GetAppBackBuffer, Window1);
  Map2.DrawClipped(GameScreen.GetAppBackBuffer, Window2);
  Map3.DrawClipped(GameScreen.GetAppBackBuffer, Window3);
  Map4.DrawClipped(GameScreen.GetAppBackBuffer, Window4);

  Result := GameScreen.Flip;
end;

procedure TfrmDD.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Hide
end;

procedure TfrmDD.ApplicationEvents1Idle(Sender: TObject;
  var Done: Boolean);
begin
  if FActive then if Failed (UpdateFrame) then begin
     GameScreen.Restore;
     GameScreen.LoadPalette('Anim.bmp');
     LandScape.Restore;
  end;
  Done := False;
end;

procedure TfrmDD.FormActivate(Sender: TObject);
begin
  FActive := True;
end;

procedure TfrmDD.FormDestroy(Sender: TObject);
begin
  if Assigned (GameInput) then GameInput.Destroy;
  if Assigned (LandScape) then LandScape.Destroy;
  if Assigned (Map1) then Map1.Destroy;
  if Assigned (Map2) then Map2.Destroy;
  if Assigned (Map3) then Map3.Destroy;
  if Assigned (Map4) then Map4.Destroy;
  if Assigned (GameScreen) then GameScreen.DestroyCDXScreen;
end;

end.


