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

DirectX角色動畫實戰(一):32位顯示模式下的鍵盤控制與幀掃描難題

     編輯:關於C語言

開發日記:從8位到32位的血淚遷徙

最初用8位顯示模式,效果慘不忍睹;改32位模式折騰數小時,做了大量無用功。素材圖更是讓人抓狂:第1、2幀掃描正常,第3、4幀死活對不齊。有大神知道原因煩請指教!

素材圖:前兩幀正常,後續幀異常

素材圖:第一行第1、2幀掃描正常,之後全部異常

目前僅掃描2幀動畫,鍵盤方向鍵控制最下方角色移動,動畫看起來略生硬,後續優化中……

核心代碼架構(DirectDraw 7)

關鍵宏定義與結構體

#define WIN32_LEAN_AND_MEAN
#define INITGUID
#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP    32
#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

// BMP位圖容器
typedef struct BITMAP_FILE_TAG {
    BITMAPFILEHEADER bitmapfileheader;
    BITMAPINFOHEADER bitmapinfoheader;
    PALETTEENTRY palette[256];
    UCHAR *buffer;
} BITMAP_FILE, *BITMAP_FILE_PTR;

// 角色對象
typedef struct ALIEN_OBJ_TYP {
    LPDIRECTDRAWSURFACE7 frames[2]; // 兩幀動畫
    int x, y;                       // 位置
    int velocity;                   // X軸速度
    int current_frame;              // 當前幀
    int counter;                    // 動畫計時
} ALIEN_OBJ, *ALIEN_OBJ_PTR;

核心函數實現

1. 位圖載入與翻轉(BMP原始數據為倒序)

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename) {
    int file_handle, index;
    OFSTRUCT file_data;
    if ((file_handle = OpenFile(filename, &file_data, OF_READ)) == -1) return 0;

    _lread(file_handle, &bitmap->bitmapfileheader, sizeof(BITMAPFILEHEADER));
    if (bitmap->bitmapfileheader.bfType != 0x4D42) { _lclose(file_handle); return 0; }

    _lread(file_handle, &bitmap->bitmapinfoheader, sizeof(BITMAPINFOHEADER));
    _llseek(file_handle, -(int)bitmap->bitmapinfoheader.biSizeImage, SEEK_END);

    if (bitmap->buffer) free(bitmap->buffer);
    bitmap->buffer = (UCHAR*)malloc(bitmap->bitmapinfoheader.biSizeImage);
    _lread(file_handle, bitmap->buffer, bitmap->bitmapinfoheader.biSizeImage);
    _lclose(file_handle);

    // 垂直翻轉
    Flip_Bitmap(bitmap->buffer,
        bitmap->bitmapinfoheader.biWidth * (bitmap->bitmapinfoheader.biBitCount/8),
        bitmap->bitmapinfoheader.biHeight);
    return 1;
}

int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height) {
    UCHAR *buffer = (UCHAR*)malloc(bytes_per_line * height);
    memcpy(buffer, image, bytes_per_line * height);
    for (int index = 0; index < height; index++)
        memcpy(&image[((height-1)-index)*bytes_per_line],
               &buffer[index*bytes_per_line], bytes_per_line);
    free(buffer);
    return 1;
}

2. DirectDraw表面創建與色彩鍵設置

LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width, int height, int mem_flags) {
    DDSURFACEDESC2 ddsd; DDRAW_INIT_STRUCT(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    ddsd.dwWidth = width; ddsd.dwHeight = height;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;

    LPDIRECTDRAWSURFACE7 lpdds;
    if (FAILED(lpdd->CreateSurface(&ddsd, &lpdds, NULL))) return 0;

    DDCOLORKEY color_key = {0, 0};
    lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);
    return lpdds;
}

3. 位圖掃描到表面(32位像素直寫)

int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, LPDIRECTDRAWSURFACE7 lpdds, int cx, int cy) {
    DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd);
    lpdds->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);

    int gwidth = ddsd.dwWidth, gheight = ddsd.dwHeight;
    cx *= gwidth; cy *= gheight;
    UCHAR *source_ptr = bitmap->buffer + cy * bitmap->bitmapinfoheader.biWidth + cx;
    DWORD *dest_ptr = (DWORD*)ddsd.lpSurface;

    for (int y = 0; y < 80; y++) {
        for (int x = cx; x < cx + gwidth; x++) {
            UCHAR blue  = bitmap->buffer[y*640*4 + x*4 + 0];
            UCHAR green = bitmap->buffer[y*640*4 + x*4 + 1];
            UCHAR red   = bitmap->buffer[y*640*4 + x*4 + 2];
            DWORD pixel = _RGB32BIT(0, red, green, blue);
            dest_ptr[x + (y * (ddsd.lPitch >> 2))] = pixel;
        }
    }
    lpdds->Unlock(NULL);
    return 1;
}

已知問題與後續計劃

  • 素材圖第3幀起掃描異常,懷疑位圖行跨度計算或素材本身排列問題。
  • 僅2幀動畫過渡生硬,需補全完整走路循環幀。
  • 後續將加入幀率獨立的動畫計時、多角色管理、碰撞檢測。

完整代碼含窗口流程、消息循環、遊戲主循環等,篇幅限制放於下篇。敬請期待!


本文出自「Chaos代碼空間」博客,轉載請保留出處。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved