首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# DirectDraw 入門攻略:DirectX 7 VB 執行庫繪圖與 Sprite 動畫實作

     編輯:關於C#

DirectX 7 時代提供 DirectDraw 進行 2D 高效繪圖,雖已被 Direct2D/Direct3D 取代,但其 API 設計清晰、透過 DxVBLib (DirectX 7 for Visual Basic 型別庫) 可在 C# 輕鬆呼叫。本文示範:建立 DirectDraw 介面、協作層級設定、Primary/Offscreen Surface 建立、Clipper 裁切、Blt/BltFast 複製、ColorKey 透明色、鍵盤驅動 Sprite 動畫等核心技術。

專案準備與參考

  1. 安裝 DirectX 7 SDK (或更新版 SDK 含向後相容)。
  2. 專案 → 加入參考 → COM → DirectX 7 for Visual Basic Type Library (命名空間 DxVBLib)。
  3. 移除不需的參考,保留 System, System.Windows.Forms, DxVBLib。

核心物件模型

介面用途
DirectX7根工廠,DirectDrawCreate()
DirectDraw7裝置管理、協作層級、Surface 建立
DirectDrawSurface7繪圖緩衝區 (Primary/Back/Offscreen)
DirectDrawClipper裁切區域限制繪圖範圍
DDSURFACEDESC2Surface 建立參數 (Capability, 寬高、像素格式)
RECT來源/目的矩形區域
DDCOLORKEY透明色範圍

初始化流程


private DxVBLib.DirectX7 dx = new DxVBLib.DirectX7();
private DxVBLib.DirectDraw7 dDraw;
private DxVBLib.DirectDrawSurface7 primarySurf, offscreenSurf, spriteSurf;
private DxVBLib.DirectDrawClipper clipper;

private void InitDirectDraw()
{
    // 1. 建立 DirectDraw 介面
    dDraw = dx.DirectDrawCreate(""); // GUID 空字串使用預設裝置

    // 2. 設定協作層級:視窗模式 (非獨佔)
    dDraw.SetCooperativeLevel(this.Handle.ToInt32(), 
        DxVBLib.CONST_DDSCLFLAGS.DDSCL_NORMAL); 
    // 全螢幕獨佔需:DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWMODEX

    // 3. 建立 Primary Surface (螢幕前景緩衝)
    var descPrimary = new DxVBLib.DDSURFACEDESC2();
    descPrimary.lFlags = DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_CAPS;
    descPrimary.ddsCaps.lCaps = DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_PRIMARYSURFACE;
    primarySurf = dDraw.CreateSurface(ref descPrimary);

    // 4. 建立 Clipper 限制繪圖於 Client 區域
    clipper = dDraw.CreateClipper(0);
    clipper.SetHWnd(this.Handle.ToInt32());
    primarySurf.SetClipper(clipper);

    // 5. 從檔案載入 Offscreen Surface (背景圖)
    var descBack = new DxVBLib.DDSURFACEDESC2();
    offscreenSurf = dDraw.CreateSurfaceFromFile("background.bmp", ref descBack);

    // 6. 從檔案載入 Sprite 圖集 (多張動作連在一張圖)
    var descSprite = new DxVBLib.DDSURFACEDESC2();
    spriteSurf = dDraw.CreateSurfaceFromFile("actor_move.bmp", ref descSprite);

    // 7. 設定 Sprite 透明色 (ColorKey) - 假設黑色背景 RGB(0,0,0)
    var ck = new DxVBLib.DDCOLORKEY();
    ck.colorSpaceLowValue = 0;
    ck.colorSpaceHighValue = 0x000000; // BGR 格式,視像素格式調整
    spriteSurf.SetColorKey(DxVBLib.CONST_DDCKEYFLAGS.DDCKEY_SRCBLT, ref ck);
}

繪圖迴圈 (OnPaint / Timer 驅動)


private DxVBLib.RECT srcRect = new DxVBLib.RECT();
private DxVBLib.RECT destRect = new DxVBLib.RECT();
private int spriteFrame = 0;
private const int FRAME_WIDTH = 140; // 每格寬度
private const int FRAME_HEIGHT = 120; // 每格高度

private void Render()
{
    // 1. 計算目的區域 (視窗客戶區置中)
    dx.GetWindowRect(this.Handle.ToInt32(), ref destRect);
    // 調整 destRect 為客戶區座標 (需扣除標題列/邊框)

    // 2. 繪製背景
    srcRect.Top = 0; srcRect.Left = 0;
    srcRect.Right = descBack.lWidth; srcRect.Bottom = descBack.lHeight;
    primarySurf.Blt(ref destRect, offscreenSurf, ref srcRect, 
        DxVBLib.CONST_DDBLTFLAGS.DDBLT_WAIT);

    // 3. 繪製 Sprite 當前幀
    srcRect.Top = 0; srcRect.Left = spriteFrame * FRAME_WIDTH;
    srcRect.Right = srcRect.Left + FRAME_WIDTH;
    srcRect.Bottom = FRAME_HEIGHT;

    // 角色置中顯示
    int cx = (destRect.Right - destRect.Left) / 2;
    int cy = (destRect.Bottom - destRect.Top) / 2;
    destRect.Left = cx - FRAME_WIDTH / 2;
    destRect.Top = cy - FRAME_HEIGHT / 2;
    destRect.Right = destRect.Left + FRAME_WIDTH;
    destRect.Bottom = destRect.Top + FRAME_HEIGHT;

    // 關鍵:DDBLT_KEYSRC 啟用 ColorKey 透明複製
    primarySurf.Blt(ref destRect, spriteSurf, ref srcRect, 
        DxVBLib.CONST_DDBLTFLAGS.DDBLT_WAIT | DxVBLib.CONST_DDBLTFLAGS.DDBLT_KEYSRC);
}

鍵盤控制 Sprite 動畫


protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    const int MOVE_STEP = 10;
    switch (keyData)
    {
        case Keys.Left:
            destRect.Left -= MOVE_STEP; destRect.Right -= MOVE_STEP;
            spriteFrame = (spriteFrame + 1) % 4; // 假設 4 幀左移動畫
            break;
        case Keys.Right:
            destRect.Left += MOVE_STEP; destRect.Right += MOVE_STEP;
            spriteFrame = (spriteFrame + 1) % 4; // 右移動畫
            break;
        case Keys.Up:
            destRect.Top -= MOVE_STEP; destRect.Bottom -= MOVE_STEP;
            break;
        case Keys.Down:
            destRect.Top += MOVE_STEP; destRect.Bottom += MOVE_STEP;
            break;
    }
    this.Invalidate(); // 觸發 OnPaint
    return base.ProcessCmdKey(ref msg, keyData);
}

protected override void OnPaint(PaintEventArgs e)
{
    Render();
    base.OnPaint(e);
}

private void Form_Resize(object sender, EventArgs e)
{
    this.Invalidate(); // 視窗大小改變重繪
}

資源釋放


protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        spriteSurf?.Release(); // COM 介面需 Release
        offscreenSurf?.Release();
        primarySurf?.Release();
        clipper?.Release();
        dDraw?.Release();
        // dx 為 RCW,由 GC 管理
    }
    base.Dispose(disposing);
}

DirectDraw 關鍵旗標速查

旗標用途
DDSCL_NORMAL視窗模式、非獨佔、GDI 相容
DDSCL_FULLSCREEN全螢幕模式
DDSCL_EXCLUSIVE獨佔模式 (需搭配 FULLSCREEN)
DDSCL_ALLOWMODEX允許 ModeX (320x240x256 等特殊模式)
DDBLT_WAIT阻塞等待 Blitter 可用
DDBLT_KEYSRC啟用來源 ColorKey 透明複製
DDBLTFAST_WAITBltFast 等待模式
DDSCAPS_PRIMARYSURFACE主要顯示 Surface
DDSCAPS_OFFSCREENPLAIN系統記憶體離屏 Surface
DDSCAPS_VIDEOMEMORY強制建立於顯示記憶體

現代化替代方案

  • Direct2D (Windows 7+ / SharpDX/Vortice):硬體加速 2D 向量/位圖繪圖,現代標準。
  • Direct3D 11/12 SpriteBatch:SharpDX.Toolkit、MonoGame 封裝,跨平台遊戲開發首選。
  • Windows.UI.Composition / Win2D:UWP/WinUI 高效能合成引擎。
  • SkiaSharp:跨平台 2D 繪圖庫 (Google Skia 封裝),支援 .NET 6+ 全平台。

常見問題

DirectDraw 雖屬歷史技術,但其 Surface、Blitter、Clipper、ColorKey、協作層級等核心概念貫穿現代 GPU 繪圖管線。透過 DxVBLib 在 C# 體驗這些基礎,有助於理解 Direct2D/Direct3D 更高層抽象背後的運作原理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
現象原因解決
畫面閃爍無雙緩衝、Primary 直接繪製建立 Back Surface 雙緩衝,或 Flip 鏈
ColorKey 不生效像素格式不符、High/Low Value 設定錯檢查 Surface 格式 (GetSurfaceDesc),BGR vs RGB
Blt 失敗Surface 損失、裝置遺失實作 RestoreSurfaces() 重建
x64 專案無法參考 DxVBLibDirectX 7 VB 型別庫僅 32-bit專案設定 Prefer 32-bit 或 x86 平台