⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameclass.pas

📁 很多人想要研究的真彩传奇2客户端,一般来说传奇2的客户端是256色的,现在出了个飞尔真彩传奇,想必很吸引大家的眼球.现在把我收藏的拿出来一起共享
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit GameClass;

interface

uses SysUtils, Graphics, DirectDraw, Windows, Messages, ClassCallback, ObjFastBlt;

const
  // MainWindow Class
  APPNAME = 'APPLICATION';

  // 全屏/窗口模式的窗口风格
  FULLSCREEN_WINDOWSTYLE = WS_VISIBLE or WS_POPUP;
  WINDOWMODE_WINDOWSTYLE = WS_VISIBLE or WS_SYSMENU or WS_MINIMIZEBOX or
    WS_POPUP or WS_DLGFRAME or WS_CAPTION;

type

  TGame = class(TObject)
  private
    FTerminated: Boolean; // 程序已终止(用于主窗口 Destroy)

    FBackDxFastBlt: TDxFastBlt;

    FDirectDraw: IDirectDraw7; // DirectDraw 句柄
    FPrimarySurface: IDirectDrawSurface7; // 主表面
    FBufferSurface: IDirectDrawSurface7; // 缓冲表面
    FClipper: IDirectDrawClipper; // 裁剪器

    FFullScreen: Boolean; // 全屏模式

    FCallbackInstance: TCallbackInstance; // 窗口回调转换代码
    FMainWindow: HWND; // 主窗口句柄
    FClientRect: TRect; // 主客户区矩形(屏幕坐标,用于 Blt)
    FActive: Boolean; // 窗口是否激活
    FCaption: string; // 窗口标题
    FWidth: Integer; // 客户区宽度
    FHeight: Integer; // 客户区高度
    FBackgroundColor: TColorRef; // 窗口背景色
    FBackgroundBrush: HBrush;
    FIsShowFPS: Boolean; // 背景画刷

    procedure SetCaption(const Value: string);
    procedure SetHeight(const Value: Integer);
    procedure SetWidth(const Value: Integer);
    procedure SetFullScreen(const Value: Boolean);
    procedure SetBackgroundColor(const Value: TColorRef);

  protected
    // 注意: WndProc 不能为虚函数,详见 ClassCallback
    function WndProc(HWND: HWND; uMsg: UINT; wParam: wParam;
      lParam: lParam): LResult; stdcall;

    function WMMouseMove(HWND: HWND; uMsg: UINT; wParam: wParam; lParam: lParam): LResult; virtual; abstract;
    function WMLButtonDown(HWND: HWND; uMsg: UINT; wParam: wParam; lParam: lParam): LResult; virtual; abstract;
    function WMLButtonUp(HWND: HWND; uMsg: UINT; wParam: wParam; lParam: lParam): LResult; virtual; abstract;
    function WMRButtonDown(HWND: HWND; uMsg: UINT; wParam: wParam; lParam: lParam): LResult; virtual; abstract;
    function WMRButtonUp(HWND: HWND; uMsg: UINT; wParam: wParam; lParam: lParam): LResult; virtual; abstract;

    procedure OnIdle;

    procedure RegisterMainWindowClass;
    procedure CreateMainWindow;

    procedure InitDirectDraw;
    procedure FreeDirectDraw;

    procedure UpdateBounds;

    function ReloadAllSurfaceImages: Boolean; virtual; abstract;
    function ProcessNextFrame: Boolean; virtual; abstract;


  public
    constructor Create(ACaption: string; AFullScreen: Boolean;
      AWidth, AHeight: Integer; ABackgroundColor: TColorRef); virtual;
    destructor Destory; virtual;

    procedure Init;
    procedure Run;
    procedure Flip;
    function ClearBufferSurface: Boolean;

    function CreateSurfaceFromText(const AText: string; AFont: HFont = 0): IDirectDrawSurface7;
    function CreateSurfaceFromBitmap(const ABitmapName: string; AColorKey: TColorRef): IDirectDrawSurface7;

    property BackDxFastBlt: TDxFastBlt read FBackDxFastBlt;
    property MainDirectDraw: IDirectDraw7 read FDirectDraw;
    property PrimarySurface: IDirectDrawSurface7 read FPrimarySurface;
    property BufferSurface: IDirectDrawSurface7 read FBufferSurface;

    property FullScreen: Boolean read FFullScreen write SetFullScreen;

    property MainWindow: HWND read FMainWindow;
    property Caption: string read FCaption write SetCaption;
    property Height: Integer read FHeight write SetHeight;
    property Width: Integer read FWidth write SetWidth;
    property BackgroundColor: TColorRef read FBackgroundColor write SetBackgroundColor;
  end;

  // 检查 DirectDraw 执行结果
procedure CheckResult(Result: HRESULT; Info: string);

implementation

procedure CheckResult(Result: HRESULT; Info: string);
var
  F: TextFile;
begin
  if Result <> DD_OK then
  begin
//    raise Exception.Create('DirectDraw Error');
//    Halt;
    FileMode := fmOpenWrite;
    AssignFile(F, ChangeFileExt(ParamStr(0), '.err'));
    Rewrite(F);
    Writeln(F, Info);
    CloseFile(F);
    Halt;
  end;
end;

{ TGame }

constructor TGame.Create(ACaption: string; AFullScreen: Boolean;
  AWidth, AHeight: Integer; ABackgroundColor: TColorRef);
begin
  FCaption := ACaption;
  FFullScreen := AFullScreen;
  FWidth := AWidth;
  FHeight := AHeight;

  FBackDxFastBlt := TDxFastBlt.Create;
  FBackDxFastBlt.Width := FWidth;
  FBackDxFastBlt.Height := FHeight;

  FBackgroundColor := ABackgroundColor;
  FBackgroundBrush := CreateSolidBrush(FBackgroundColor);


  FIsShowFPS := True;

  // 生成类回调函数
  MakeCallbackInstance(FCallbackInstance, Self, @TGame.WndProc);

  // 注册主窗口类
  RegisterMainWindowClass;

  // 初始化 DirectDraw
  InitDirectDraw;
end;

destructor TGame.Destory;
begin
  // 清除 DirectDraw 对象
  FreeDirectDraw;
  // 清除 背景画刷
  DeleteObject(FBackgroundBrush);

  FBackDxFastBlt.Free;
end;

procedure TGame.InitDirectDraw;
var
  DDSD: TDDSurfaceDesc2;
begin
  // 删除原来的窗口,由 WM_DESTROY 负责删除原 DirectDraw 对象
  if IsWindow(FMainWindow) then DestroyWindow(FMainWindow);

  // 创建主窗口
  CreateMainWindow;

  // 创建 FDirectDraw
  CheckResult(DirectDrawCreateEx(nil, FDirectDraw, IID_IDirectDraw7, nil),
    'DirectDrawCreateEx');

  // 根据全屏或窗口模式创建表面
  // 全屏模式
  if FFullScreen then
  begin
    CheckResult(FDirectDraw.SetCooperativeLevel(FMainWindow, DDSCL_EXCLUSIVE or
      DDSCL_FULLSCREEN), ' SetCooperativeLevel');

    CheckResult(FDirectDraw.SetDisplayMode(FWidth, FHeight, 8, 0, 0),
      'SetDisplayMode');

    FillChar(DDSD, SizeOf(DDSD), #0);
    DDSD.dwSize := SizeOf(DDSD);
    DDSD.dwFlags := DDSD_CAPS { or DDSD_BACKBUFFERCOUNT};
//  DirectX 例子中的写法
//    DDSD.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or
//      DDSCAPS_COMPLEX or DDSCAPS_3DDEVICE;
    DDSD.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE {or DDSCAPS_FLIP or DDSCAPS_COMPLEX};
//    DDSD.dwBackBufferCount := 1;
    CheckResult(FDirectDraw.CreateSurface(DDSD, FPrimarySurface, nil),
      'CreateSurface: FPrimarySurface');

//    FillChar(DDSCaps, SizeOf(DDSCaps), #0);
//    DDSCaps.dwCaps := DDSCAPS_BACKBUFFER;
//    CheckResult(FPrimarySurface.GetAttachedSurface(DDSCaps, FBufferSurface),
//      'FPrimarySurface.GetAttachedSurface');
    DDSD.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
    DDSD.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY; //or DDSCAPS_3DDEVICE;
    DDSD.dwHeight := FHeight;
    DDSD.dwWidth := FWidth;
    CheckResult(FDirectDraw.CreateSurface(DDSD, FBufferSurface, nil),
      'CreateSurface(CreateSurface(FBufferSurface in Window Mode)');

  end
  // 窗口模式
  else begin
    CheckResult(FDirectDraw.SetCooperativeLevel(FMainWindow, DDSCL_NORMAL),
      'SetCooperativeLevel(FMainWindow, DDSCL_NORMAL)');

    // TODO: 修正
    {CheckResult(FDirectDraw.SetDisplayMode(1024, 768, 8, 0, 0),  修改 窗口模式不修改分辨率
      'SetDisplayMode'); }

    FillChar(DDSD, SizeOf(DDSD), #0);
    DDSD.dwSize := SizeOf(DDSD);
    DDSD.dwFlags := DDSD_CAPS;
    DDSD.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;
    CheckResult(FDirectDraw.CreateSurface(DDSD, FPrimarySurface, nil),
      'CreateSurface(FPrimarySurface in Window Mode)');

    DDSD.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
    DDSD.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY; //or DDSCAPS_3DDEVICE;
    DDSD.dwHeight := FHeight;
    DDSD.dwWidth := FWidth;
    CheckResult(FDirectDraw.CreateSurface(DDSD, FBufferSurface, nil),
      'CreateSurface(CreateSurface(FBufferSurface in Window Mode)');

    CheckResult(FDirectDraw.CreateClipper(0, FClipper, nil),
      'CreateClipper in Window Mode');
    CheckResult(FClipper.SetHWnd(0, FMainWindow), 'FClipper.SetHWnd');
    CheckResult(FPrimarySurface.SetClipper(FClipper), 'FPrimarySurface.SetClipper');
    FClipper := nil;
  end;
end;

procedure TGame.RegisterMainWindowClass;
var
  AWndClass: TWndClassEx;
begin
  FillChar(AWndClass, SizeOf(AWndClass), #0);
  AWndClass.cbSize := SizeOf(AWndClass);
  AWndClass.Style := 0;
  AWndClass.lpfnWndProc := @FCallbackInstance;
  AWndClass.cbClsExtra := 0;
  AWndClass.cbWndExtra := 0;
  AWndClass.hInstance := hInstance;
  AWndClass.hIcon := LoadIcon(hInstance, 'MAINICON');
  AWndClass.hIconSm := AWndClass.hIcon;
  AWndClass.hCursor := LoadCursor(0, IDI_APPLICATION);
  AWndClass.hbrBackground := FBackgroundBrush;
  AWndClass.lpszMenuName := nil;
  AWndClass.lpszClassName := APPNAME;

  //TODO: exception handler
  if RegisterClassEx(AWndClass) = INVALID_ATOM then
    raise Exception.Create('Can not register window class!');
end;

procedure TGame.CreateMainWindow;
var
  Style: Cardinal;
  BorderX, BorderY, CaptionY: Integer;
  ALeft, ATop, AWidth, AHeight: Integer;
begin
  if FFullScreen then
  begin
    Style := FULLSCREEN_WINDOWSTYLE;

    ALeft := 0;
    ATop := 0;
    AWidth := GetSystemMetrics(SM_CXSCREEN);
    AHeight := GetSystemMetrics(SM_CYSCREEN);
  end
  else begin
    Style := WINDOWMODE_WINDOWSTYLE;

    BorderX := GetSystemMetrics(SM_CXDLGFRAME);
    BorderY := GetSystemMetrics(SM_CYDLGFRAME);
    CaptionY := GetSystemMetrics(SM_CYCAPTION);
    AWidth := FWidth + BorderX * 2;
    AHeight := FHeight + BorderY * 2 + CaptionY;

    ALeft := (GetSystemMetrics(SM_CXSCREEN) - AWidth) div 2;
    ATop := (GetSystemMetrics(SM_CYSCREEN) - AHeight) div 2;
  end;

  FMainWindow := CreateWindow(APPNAME, PChar(FCaption), Style,
    ALeft, ATop, AWidth, AHeight, 0, 0, hInstance, nil);

  // TODO: Exception
  if not IsWindow(FMainWindow) then
    raise Exception.Create('Can not create window!');

  UpdateBounds;
end;

procedure TGame.Flip;
var
  Result: HRESULT;
  DDSD: TDDSurfaceDesc2;
        //TDDSurfaceDesc
begin
  // 检查指针合法性
  // if (FPrimarySurface = nil) or (FBufferSurface = nil) then Exit;

  // 全屏模式
  // TODO: 为什么全屏模式下 flip 比 blt 更慢?
//  if FFullScreen then
//    Result := FPrimarySurface.Flip(nil, DDFLIP_WAIT)
//  else
  FillChar(DDSD, SizeOf(DDSD), #0);
  DDSD.dwSize := SizeOf(DDSD);
  if FBufferSurface.Lock(nil, DDSD, DDLOCK_WAIT, 0) = DD_OK then begin
    FBackDxFastBlt.DrawOnSurface(DDSD, False);    //FBackDxFastBlt画到 FBufferSurface
    FBufferSurface.Unlock(nil);
  end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -