|
|
rt,是按照 《游戏编程大师技巧》里面的知识写的,个人觉得跟例子代码差不多,但是书里面的代码可以正常显示8位的bmp位图,而我的显示暗淡。但是形状基本没有变,就像没有光照的样子,小弟初学游戏编程,刚走了没有几步,就有问题啦,哪位大哥帮忙看看啊,万分感谢。
代码如下:
// Game7.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include "ddraw.h"
#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"
#define MAX_LOADSTRING 100
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000)?1:0)
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
LPDIRECTDRAW7 lpdd7;
LPDIRECTDRAWPALETTE lpddpal;
LPDIRECTDRAWSURFACE7 lpddprimarysurface;
LPDIRECTDRAWSURFACE7 lpddbacksurface;
HWND g_hWnd;
PALETTEENTRY g_palette[256];
DDSURFACEDESC2 g_ddsur;
DDSURFACEDESC2 ddsd;
DDSCAPS2 ddsCaps;
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
typedef struct BITMAP_FILE_TAG
{
BITMAPFILEHEADER bitmapfileheader;
BITMAPINFOHEADER bitmapinfoheader;
PALETTEENTRY palette[256];
UCHAR * Buffer;
}BITMAP_FILE;
BITMAP_FILE bitmap;
//位图数据翻转函数
void Flip_Bitmap(UCHAR *buffer,int size_per_line,int lines)
{
UCHAR * temp_buffer=(UCHAR *)malloc(size_per_line *lines);
memcpy(temp_buffer,buffer,size_per_line*lines);
for (int i=0;i<lines;i++)
{
memcpy(&buffer[(lines-i-1)*size_per_line],&temp_buffer[i*size_per_line],size_per_line);
}
free(temp_buffer);
}
//这个函数从盘上读取BMP文件信息,放入到BITMAP_FILE这个结构中
int Load_Bitmap_File(BITMAP_FILE *bitmap,char *filename)
{
FILE *pfile;
pfile=fopen(filename,"r");
if (pfile==NULL)
{
MessageBox(g_hWnd,"打开BMP文件失败","提示",NULL);
return 0;
}
fread(&(bitmap->bitmapfileheader),1,sizeof(BITMAPFILEHEADER),pfile);
if (bitmap->bitmapfileheader.bfType !=0x4D42)
{
fclose(pfile);
MessageBox(g_hWnd,"不是BMP文件,不能解析","提示",NULL);
return 0;
}
fread(&(bitmap->bitmapinfoheader),1,sizeof(BITMAPINFOHEADER),pfile);
if (bitmap->bitmapinfoheader.biBitCount==8)//如果是8位读入调色板信息
{
fread(&(bitmap->palette),1,sizeof(PALETTEENTRY)*256,pfile);
for (int i=0;i<256;i++)//颠倒颜色顺序
{
int temp_color=bitmap->palette.peRed;
bitmap->palette.peRed=bitmap->palette.peBlue;
bitmap->palette.peBlue=temp_color;
bitmap->palette.peFlags=PC_NOCOLLAPSE;
}
}
fseek(pfile,(bitmap->bitmapinfoheader.biSizeImage)*(-1),SEEK_END);//定位文件指针到真正的位图数据块
//下面拷贝真正的位图数据
if (bitmap->bitmapinfoheader.biBitCount==8 ||bitmap->bitmapinfoheader.biBitCount==16 ||bitmap->bitmapinfoheader.biBitCount==24)
{
if (bitmap->Buffer)//如果有数据,释放
{
free(bitmap->Buffer);
}
//申请内存空间
bitmap->Buffer=(UCHAR *)malloc (bitmap->bitmapinfoheader.biSizeImage);
if (bitmap->Buffer==NULL)
{
fclose(pfile);
MessageBox(g_hWnd,"文件数据内存分配失败","提示",NULL);
return 0;
}
fread(bitmap->Buffer,1,bitmap->bitmapinfoheader.biSizeImage,pfile);
}
else
{
MessageBox(g_hWnd,"颜色深度不对","提示",NULL);
return 0;
}
//关闭文件指针
fclose(pfile);
//下面翻转位图数据
if (bitmap->bitmapinfoheader.biHeight>0)
{
//MessageBox(g_hWnd,"翻转位图","提示",NULL);
Flip_Bitmap(bitmap->Buffer,(bitmap->bitmapinfoheader.biWidth)*(bitmap->bitmapinfoheader.biBitCount)/8,bitmap->bitmapinfoheader.biHeight);
}
return 1;
}
int Unload_Bitmap_File(BITMAP_FILE * bitmap)
{
if (bitmap->Buffer)
{
free(bitmap->Buffer);
}
bitmap->Buffer=NULL;
return 1;
}
int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color)
{
DDBLTFX ddbltfx;
ddbltfx.dwSize=sizeof(DDBLTFX);
ddbltfx.dwFillColor = color;
lpdds->Blt(NULL,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&ddbltfx);
return(1);
}
int Game_Init(void *parms=NULL, int num_parms=0)
{
//获得DirectDraw7接口
if (FAILED(DirectDrawCreateEx(NULL,(void **)&lpdd7,IID_IDirectDraw7,NULL)))
{
MessageBox(g_hWnd,"DirectDraw7获取失败","提示",NULL);
return 0;
}
//设置与windows协作
if(FAILED(lpdd7->SetCooperativeLevel(g_hWnd,DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |DDSCL_EXCLUSIVE |DDSCL_ALLOWREBOOT)))
{
MessageBox(g_hWnd,"与windows协作失败","提示",NULL);
return 0;
}
//设置视频模式
if(FAILED(lpdd7->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)))
{
MessageBox(g_hWnd,"设置视频模式失败","提示",NULL);
return 0;
}
//创建调色板
for (int i=1;i<255;i++)
{
g_palette.peRed=rand()%256;
g_palette.peGreen=rand()%256;
g_palette.peBlue=rand()%256;
g_palette.peFlags=PC_NOCOLLAPSE;
}
g_palette[0].peRed=0;
g_palette[0].peGreen=0;
g_palette[0].peBlue=0;
g_palette[0].peFlags=PC_NOCOLLAPSE;
g_palette[255].peRed=255;
g_palette[255].peGreen=255;
g_palette[255].peBlue=255;
g_palette[255].peFlags=PC_NOCOLLAPSE;
if(FAILED(lpdd7->CreatePalette(DDPCAPS_8BIT |DDPCAPS_ALLOW256 |DDPCAPS_INITIALIZE,g_palette,&lpddpal,NULL)))
{
MessageBox(g_hWnd,"创建调色板失败","提示",NULL);
return 0;
}
//创建主显示表面
g_ddsur.dwSize=sizeof(DDSURFACEDESC2);
g_ddsur.dwFlags=DDSD_CAPS;
g_ddsur.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
if(FAILED(lpdd7->CreateSurface(&g_ddsur,&lpddprimarysurface,NULL)))
{
MessageBox(g_hWnd,"创建主显示表面失败","提示",NULL);
return 0;
}
//关联主显示表面和调色板
if ( FAILED(lpddprimarysurface->SetPalette(lpddpal)))
{
MessageBox(g_hWnd,"主表面关联调色板失败","提示",NULL);
return 0;
}
if(Load_Bitmap_File(&bitmap,"bitmap8.bmp")==0)
{
MessageBox(g_hWnd,"读取位图失败","提示",NULL);
return 0;
}
//改变调色板
if (FAILED(lpddpal->SetEntries(0,0,256,bitmap.palette)))
{
MessageBox(g_hWnd,"调入位图调色板失败","提示",NULL);
return 0;
}
// clean the surface
//DDraw_Fill_Surface(lpddprimarysurface,0);
return 1;
}
int Game_ShutDown(void *parms=NULL, int num_parms=0)
{
if (lpddprimarysurface)
{
lpddprimarysurface->Release();
lpddprimarysurface=NULL;
}
if (lpddpal)
{
lpddpal->Release();
lpddpal=NULL;
}
if (lpdd7)
{
lpdd7->Release();
lpdd7=NULL;
}
Unload_Bitmap_File(&bitmap);
return 1;
}
int Game_Main(void *parms=NULL, int num_parms=0)
{
if (KEYDOWN(VK_ESCAPE))
{
SendMessage(g_hWnd,WM_CLOSE,0,0);
}
//锁定主显示表面
ddsd.dwSize=sizeof(DDSURFACEDESC2);
if (FAILED( lpddprimarysurface->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL)))
{
MessageBox(g_hWnd,"锁定主显示表面失败","提示",NULL);
return 0;
}
UCHAR *primary_buffer=(UCHAR *)ddsd.lpSurface;
if (ddsd.lPitch == SCREEN_WIDTH)
{
memcpy((void *)primary_buffer, (void *)bitmap.Buffer, SCREEN_WIDTH*SCREEN_HEIGHT);
}
else
{
UCHAR *dest_ptr = primary_buffer;
UCHAR *src_ptr = bitmap.Buffer;
for (int y=0; y < SCREEN_HEIGHT; y++)
{
memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH);
dest_ptr+=ddsd.lPitch;
src_ptr +=SCREEN_WIDTH;
}
}
// now unlock the primary surface
if (FAILED(lpddprimarysurface->Unlock(NULL)))
return(0);
return 1;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
int start_tick;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_GAME7, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_GAME7);
// Main message loop:
Game_Init();
while (1)
{
start_tick=GetTickCount();
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Game_Main();
while (GetTickCount()-start_tick<33);
}
Game_ShutDown();
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_DBLCLKS |CS_HREDRAW | CS_VREDRAW| CS_OWNDC;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_GAME7);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
//wcex.lpszMenuName = (LPCSTR)IDC_GAME3;
wcex.lpszMenuName=NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_POPUP | WS_VISIBLE,
0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);
g_hWnd=hWnd;
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
|
|