最初用8位顯示模式,效果慘不忍睹;改32位模式折騰數小時,做了大量無用功。素材圖更是讓人抓狂:第1、2幀掃描正常,第3、4幀死活對不齊。有大神知道原因煩請指教!
素材圖:第一行第1、2幀掃描正常,之後全部異常
目前僅掃描2幀動畫,鍵盤方向鍵控制最下方角色移動,動畫看起來略生硬,後續優化中……
#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;
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;
}
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;
}
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;
}
完整代碼含窗口流程、消息循環、遊戲主循環等,篇幅限制放於下篇。敬請期待!
本文出自「Chaos代碼空間」博客,轉載請保留出處。