关于bltFast问题,无法显示图像,在线等待,错误在draw_slide函数中的bitfast

flyukeer 2008-03-22 12:53:24
// PicSlide.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#define INITGUID
#include <stdio.h>
#include <ddraw.h>
#include <mmsystem.h>
static char szClass[]="XmplHr3Class";
static char szCaption[]="Example - Hour 3";


LPDIRECTDRAW7 lpDD=NULL;
LPDIRECTDRAWSURFACE7 lpDDSPrimary=NULL;
LPDIRECTDRAWSURFACE7 lpDDSBack=NULL;
LPDIRECTDRAWCLIPPER lpClip=NULL;
#define IMAGE_COUNT 7
char file_names[IMAGE_COUNT][256]={"23.bmp",
"24.bmp",
"25.bmp",
"26.bmp",
"27.bmp",
"28.bmp",
"29.bmp"
};
static BOOL Init(HINSTANCE hInstance,int nCmdShow);
LPDIRECTDRAWSURFACE7 lpSlides[IMAGE_COUNT];
int cur_image=0;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LPDIRECTDRAWSURFACE7 bitmap_surface(LPCTSTR file_name);
void draw_slide();
#define SafeRelease(x) if (x) {x->Release();x=NULL;}
void Cleanup();

static BOOL Init(HINSTANCE hInstance,int nCmdShow)
{
WNDCLASS wcex;
HRESULT hRet;


wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(DWORD);
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szClass;
if (!RegisterClass(&wcex))
{
return FALSE;
}

int ScreenWidth=GetSystemMetrics(SM_CXSCREEN);
int ScreenHeight=GetSystemMetrics(SM_CYSCREEN);
HWND hWnd;
hWnd=CreateWindow(szClass,szCaption,WS_VISIBLE|WS_POPUP,0,0,ScreenWidth,ScreenHeight,NULL,NULL,hInstance,NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);

hRet=DirectDrawCreateEx(NULL,(LPVOID *)&lpDD,IID_IDirectDraw7,NULL);
if (hRet != DD_OK)
{
return FALSE;
}

hRet=lpDD->SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
// hRet=lpDD->SetCooperativeLevel(hWnd,DDSCL_NORMAL);
if (hRet != DD_OK)
{
return FALSE;
}
hRet=lpDD->SetDisplayMode(1280,800,16,0,0);
if (hRet!=DD_OK)
{
return FALSE;
}
DDSCAPS2 ddscaps;
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddscaps,sizeof(DDSCAPS2));
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount=1;

hRet=lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL);
if (hRet!=DD_OK)
{
return FALSE;
}

ddscaps.dwCaps=DDSCAPS_BACKBUFFER;
hRet=lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack);

if (hRet!=DD_OK)
{
return FALSE;
}
lpSlides[0]=bitmap_surface(file_names[0]);

draw_slide();

// hRet=lpDD->CreateClipper(NULL,&lpClip,NULL);
// if (hRet!=DD_OK)
// {
// return FALSE;
// }
// lpClip->SetHWnd(0,hWnd);
// lpDDSPrimary->SetClipper(lpClip);

return TRUE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
if (!Init(hInstance,nCmdShow))
{
return FALSE;
}
while(GetMessage(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_LEFT:
cur_image--;
if(cur_image<0)
{
cur_image=IMAGE_COUNT-1;
}
draw_slide();
break;
case VK_RIGHT:
cur_image++;
if (cur_image>IMAGE_COUNT-1)
{
cur_image=0;
}
draw_slide();
break;
case VK_ESCAPE:
DestroyWindow(hWnd);
break;
default:
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LPDIRECTDRAWSURFACE7 bitmap_surface(LPCTSTR file_name)
{
HDC hdc;
HBITMAP bit;
LPDIRECTDRAWSURFACE7 surf;
bit=(HBITMAP)LoadImage(NULL,file_name,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);
if (!bit)
return NULL;
BITMAP bitmap;
GetObject(bit,sizeof(BITMAP),&bitmap);
int surf_width=bitmap.bmWidth;
int surf_height=bitmap.bmHeight;

HRESULT hRet;
// ZeroMemory(surf,sizeof(LPDIRECTDRAWSURFACE7));
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(DDSURFACEDESC2);
ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth=surf_width;
ddsd.dwHeight=surf_height;
hRet=lpDD->CreateSurface(&ddsd,&surf,NULL);
if (hRet!=DD_OK)
{
DeleteObject(bit);
return NULL;
}
else
{
surf->GetDC(&hdc);
HDC bit_dc=CreateCompatibleDC(hdc);
SelectObject(bit_dc,bit);
BitBlt(hdc,0,0,surf_width,surf_height,bit_dc,0,0,SRCCOPY);
surf->ReleaseDC(bit_dc);
}
DeleteObject(bit);
return surf;
}
void draw_slide()
{
HRESULT hRet;
if (!lpSlides[cur_image])
{
lpSlides[cur_image]=bitmap_surface(file_names[cur_image]);
if (!lpSlides[cur_image])
return;
}
// hRet=lpDDSBack->BltFast(0,0,lpSlides[cur_image],NULL,DDBLTFAST_WAIT);
DDBLTFX ddbltfx;
hRet=lpDDSBack->Blt(NULL,lpSlides[cur_image],NULL,DDBLT_WAIT,&ddbltfx);
// switch(hRet)
// {
// case DDERR_EXCEPTION:
// MessageBox(NULL,"DDERR_EXCEPTION","错误",MB_OK);
// break;
// case DDERR_GENERIC:
// MessageBox(NULL,"DDERR_GENERIC","错误",MB_OK);
// break;
// case DDERR_INVALIDOBJECT:
// MessageBox(NULL,"DDERR_INVALIDOBJECT","错误",MB_OK);
// break;
// case DDERR_INVALIDPARAMS:
// MessageBox(NULL,"DDERR_INVALIDPARAMS","错误",MB_OK);
// break;
// case DDERR_INVALIDRECT:
// MessageBox(NULL,"DDERR_INVALIDRECT","错误",MB_OK);
// break;
// case DDERR_NOBLTHW:
// MessageBox(NULL,"DDERR_NOBLTHW","错误",MB_OK);
// break;
// case DDERR_SURFACEBUSY:
// MessageBox(NULL,"DDERR_SURFACEBUSY","错误",MB_OK);
// break;
// case DDERR_SURFACELOST:
// MessageBox(NULL,"DDERR_SURFACELOST","错误",MB_OK);
// break;
// case DDERR_UNSUPPORTED:
// MessageBox(NULL,"DDERR_UNSUPPORTED","错误",MB_OK);
// break;
// case DDERR_WASSTILLDRAWING:
// MessageBox(NULL,"DDERR_WASSTILLDRAWING","错误",MB_OK);
// break;
// }
HDC hdc;
if (DD_OK==lpDDSBack->GetDC(&hdc))
{
SetTextColor(hdc,0x00FF7F00);
SetBkColor(hdc,0x000000);
TextOut(hdc,20,700,"<-Previous Slide",16);
TextOut(hdc,1000,700,"Next Slide ->",13);
SetTextColor(hdc,0x0000FFFF);
TextOut(hdc,400,750,"Press Arrow Keys to Change Slides",33);
lpDDSBack->ReleaseDC(hdc);
}

lpDDSPrimary->Flip(0,DDFLIP_WAIT);

int next_slide=(cur_image>=IMAGE_COUNT-1)?0:cur_image+1;
if (!lpSlides[next_slide])
{
lpSlides[next_slide]=bitmap_surface(file_names[next_slide]);
}
int prev_slide=(cur_image<1)?IMAGE_COUNT-1:cur_image-1;
if (!lpSlides[prev_slide])
{
lpSlides[prev_slide]=bitmap_surface(file_names[prev_slide]);
}
}
void Cleanup()
{
for (int i=0;i<IMAGE_COUNT;i++)
{
SafeRelease(lpSlides[i]);
}
SafeRelease(lpDDSPrimary);
SafeRelease(lpDDSBack);
SafeRelease(lpDD);
}
...全文
103 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
meiZiNick 2008-05-01
  • 打赏
  • 举报
回复
好像没那么简单,呵呵.
UltraBejing 2008-05-01
  • 打赏
  • 举报
回复
接分先!
flyukeer 2008-03-26
  • 打赏
  • 举报
回复
怎么没有人回答?问了好多人都找不出原因啊
用DDraw实现射击游戏说明文档 要点一:画图自动切割 IDirectDrawSurface7::BltFast()方法没有自动切割功能,即当画图元素超出窗口以外时不会自动切割,DDraw选择自动忽略不画,造成一旦超出窗口,画图元素会突然消失。 解决这一问题的方法是手动切割,代码如下: //自动切割 RECT scRect; //存放当前窗口大小区域 ZeroMemory( &scRect, sizeof( scRect ) ); GetWindowRect( GetActiveWindow(), &scRect ); //防止图片左上角超过窗口左上角 if ( x < 0 ) { m_rect.left -= x; x = 0; } if ( y scRect.right ? scRect.right : x; y = y > scRect.bottom ? scRect.bottom : y; m_rect.right = x + m_rect.right - m_rect.left > scRect.right ? scRect.right - x + m_rect.left : m_rect.right; m_rect.bottom = y + m_rect.bottom - m_rect.top > scRect.bottom ? scRect.bottom - y + m_rect.top : m_rect.bottom; 只需将上述代码加在CGraphic::BltBBuffer() 的m_bRect = m_rect; 前即可。 要点二:背景的滚轴实现 画背景可以分为以下三种情况: 情况一:背景图片与窗口等高 情况二:背景图片高度小于窗口高度 情况三:背景图片高度大于窗口高度 上述讲解图与代码相对应地看,有助于容易理解。 另外,要点一实现之后,由于已经可以自动切割,画背景可以用其它方法。 要点三:精灵图的实现 在游戏,如RPG游戏的人物图、射击类游戏的飞机、爆炸等,叫做精灵图。 精灵图实际上是将所有帧的图片放在一个文件,游戏时靠一个RECT来控制画图像文件的哪一部分,进而控制游戏显示哪一帧图,只需控制好RECT的位置即可。如下图: 控制RECT的四个角的坐标的移动,有以下代码: if (m_timeEnd – m_timeStart > 100) //只有到了100ms之后才绘图 { m_ImageID++; if(m_ImageID - m_beginID >= num) { m_ImageID = m_beginID; //最后一帧的下一帧是第一帧 } m_timeStart = timeGetTime(); } int id = m_ImageID++; SetRect(&m_rect, 41 * id, 0, 41 * (id + 1), 41); //飞机精灵图大小是41×41 m_pGraph->BltBBuffer(m_pImageBuffer, true, m_Pos.x, m_Pos.y, m_rect); 这样就实现了精灵动画的效果。 要点四:拿STL进行子弹的实现 子弹的实现可以使用STL的vector,当按下开火键时发出一颗子弹,就往vector添加一个结点;当子弹飞出窗口或击敌机时,再将结点从vector删除。每帧游戏画面子弹飞行时只需将vector的所有子弹进行处理、绘画即可。 参考代码如下: 1.添加子弹 if (g_ctrlDown) //当ctrl键按下时开炮! { m_BulletEnd = m_Gtime->GetTime(); if ((m_BulletEnd - m_BulletStart) * 1000 > 120) //如果连续按着开火键不放,这里控制不会发出太多子弹 { m_BulletStart = m_BulletEnd; MBULLET tmpBullet; tmpBullet.pos.x = m_SPos.x - 1; //记录开火时的子弹位置 tmpBullet.pos.y = m_SPos.y - 26; tmpBullet.speed = 5; //该子弹的飞行速度 m_BulletList.push_back(tmpBullet); //将子弹添加到vector

8,305

社区成员

发帖
与我相关
我的任务
社区描述
游戏开发相关内容讨论专区
社区管理员
  • 游戏开发
  • 呆呆敲代码的小Y
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧