// Graphic.h: interface for the CGraphic class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRAPHIC_H__AEDE17EF_1768_44AF_854B_EB2C98936FAB__INCLUDED_) #define AFX_GRAPHIC_H__AEDE17EF_1768_44AF_854B_EB2C98936FAB__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "head.h" class CGraphic { private: bool m_bfScreen; // 是否全屏(在WIN32下通常都为全屏) DWORD m_dwHeight; // 屏幕高 DWORD m_dwWidth; // 屏幕宽 DWORD m_dwCDepth; // 颜色深度(8位、16位、32位、64位,通常为32位) HWND m_hWnd; // 窗口句柄 LPDIRECTDRAW7 m_pDD7; // DirectDraw对象 LPDIRECTDRAWSURFACE7 m_pPSur; // 前(页)缓冲 LPDIRECTDRAWSURFACE7 m_pBBuf; // 后(页)缓冲 RECT m_bRect; RECT m_rcRect; DDCOLORKEY m_key; // 颜色键值 LPDIRECTDRAWCLIPPER lpDDclip; // Directdraw剪切板(用途相当于把图纸上的没用的东西剪掉,留下我们要看的东西) POINT m_MPos; //--光标的位置 public: CGraphic(); virtual ~CGraphic(); LPDIRECTDRAWSURFACE7 GetPBuffer() { return m_pPSur; } LPDIRECTDRAWSURFACE7 GetBBuffer() { return m_pBBuf; } //---------------------------------------------------------------------------------------- //Name: InitDDraw 初始化离屏窗体 //Desc: hWnd 当前窗口 // bfScreen 是否全屏 // Width 屏幕宽 // Height 屏幕高 // CDepth 颜色深度 //---------------------------------------------------------------------------------------- bool InitDDraw(HWND hWnd,bool bfScreen,DWORD Height,DWORD Width,DWORD CDepth); //---------------------------------------------------------------------------------------- //Name: LoadToOffScreen 初始化离屏缓冲区(加载位图) //Desc: oBuffer为指向离屏缓冲区的指针 dwWidth 离屏缓存区的宽, // dwHeight离屏缓存区的高, BitMapFile 位图源文件 // b_ColorKey 是否需要透明 color 透明色 //---------------------------------------------------------------------------------------- bool LoadToOffScreen(LPDIRECTDRAWSURFACE7& oBuffer,DWORD dwWidth,DWORD dwHeight, LPCSTR BitMapFile,bool b_ColorKey,DWORD color); //---------------------------------------------------------------------------------------- //Name: BltBBuffer 画图 //Desc: oBuffer 缓冲 // b_ColorKey 是否需要透明, // x 图片的X坐标 // y 图片的Y坐标 // ClipX 图片抠像X起点 // ClipY 图片抠像Y起点 // ClipEndX 图片抠像X结束点 // CLipEndY 图片抠像Y结束点 //---------------------------------------------------------------------------------------- void BltBBuffer(LPDIRECTDRAWSURFACE7 oBuffer,bool b_ColorKey,int x ,int y, int ClipX, int ClipY, int ClipEndX, int CLipEndY); // 翻页 void Flip(); // 清除当前图片资源(这样可以重新加载一个新的图片进来) void ClearBuffer(LPDIRECTDRAWSURFACE7& Buffer); // 文字输出 void OutText(LPCSTR str, int x, int y,COLORREF color); // 设置鼠标区域(加载鼠标图片时可以使用) void SetMouseRect(RECT* m_rect, int scWidth, int scHeight, int msWidth, int msHeight);// 光标 /*void CopyToBuffer(LPDIRECTDRAWSURFACE7& SrcBuffer,LPDIRECTDRAWSURFACE7& DestBuffer, bool b_ColorKey,int x,int y,RECT m_rect); void CopyToBuffer(LPDIRECTDRAWSURFACE7& SrcBuffer,LPDIRECTDRAWSURFACE7& DestBuffer, bool b_ColorKey,float zoomX, float zoomY);*/ //void Flip(int x, int y, RECT m_rect); private: //---------------------------------------------------------------------------------------- //Name: InitOffScreen 初始化离屏缓冲区,类内部使用,LoadToOffScreen()函数调用,外部不需要 //Desc: oBuffer为指向离屏缓冲区的指针 dwWidth 离屏缓存区的宽, // dwHeight离屏缓存区的高, b_ColorKey 是否需要做透明 // color 透明色 //---------------------------------------------------------------------------------------- bool InitOffScreen(LPDIRECTDRAWSURFACE7& oBuffer,DWORD dwWidth,DWORD dwHeight, bool b_ColorKey,DWORD color); // 设置透明的颜色值(内部调用) void DDColorKey(LPDIRECTDRAWSURFACE7 oBuffer,DWORD color); }; #endif // !defined(AFX_GRAPHIC_H__AEDE17EF_1768_44AF_854B_EB2C98936FAB__INCLUDED_)
// Graphic.cpp: implementation of the CGraphic class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Graphic.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// DDSURFACEDESC2 desc; // 剪裁属性(前页主绘属性) DDSCAPS2 caps; // 剪裁属性(后页属性) CGraphic::CGraphic() { m_bfScreen = true; m_dwWidth = 1024; m_dwHeight = 768; m_dwCDepth = 32; m_hWnd = NULL; m_pDD7 = NULL; m_pPSur = NULL; m_pBBuf = NULL; lpDDclip = NULL; } CGraphic::~CGraphic() { SafeRelease(lpDDclip);//删除剪裁 } //---------------------------------------------------------------------------------------- //Name: InitDDraw 初始化离屏窗体 //Desc: hWnd 当前窗口 // bfScreen 是否全屏 // Width 屏幕宽 // Height 屏幕高 // CDepth 颜色深度 //---------------------------------------------------------------------------------------- bool CGraphic::InitDDraw(HWND hWnd,bool bfScreen,DWORD Width,DWORD Height,DWORD CDepth) { m_hWnd = hWnd; //窗口句柄 m_bfScreen = bfScreen; //是否全屏 m_dwWidth = Width; //屏幕的宽 m_dwHeight = Height; //屏幕的高 m_dwCDepth = CDepth; //颜色深度 HRESULT result; // 创建一个DirectDraw对象 result = DirectDrawCreateEx(NULL, // 用当前的显示驱动 (VOID**)&m_pDD7, // DirectDraw对象 IID_IDirectDraw7, // 使用版本7,目前Draw的最高版本吧 NULL); // 其它参数,没有,默认为NULL if (result != DD_OK) { MessageBox(NULL, "建立DirectDraw对象失败!", NULL, MB_OK); return false; } if(m_bfScreen) { // 设定程序协调层级 // result = m_pDD7->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); // 窗口模式,MFC中可使用,目前在WIN32还没有找到怎么使用它 result = m_pDD7->SetCooperativeLevel(m_hWnd, // 当前窗口 DDSCL_EXCLUSIVE // 独占 |DDSCL_FULLSCREEN); // 全屏 if(result != DD_OK) { MessageBox(NULL, "设定程序协调层级失败!", NULL, MB_OK); return false; } // 设定屏幕显示模式(此模式将把显示器的显示模式一起改变,当窗口关闭后,将被还原) result = m_pDD7->SetDisplayMode(m_dwWidth, // 宽 m_dwHeight, // 高 m_dwCDepth, // 颜色深度 0, DDSDM_STANDARDVGAMODE); if(result != DD_OK) { MessageBox(NULL, "设定屏幕显示模式失败!", NULL, MB_OK); return false; } //创剪裁器(必须在设置完DirectDraw控制级后,创建主页面之前进行) result=m_pDD7->CreateClipper(NULL,&lpDDclip,NULL); if(result != MB_OK) { return FALSE; } lpDDclip->SetHWnd(0,m_hWnd); // 设置剪裁窗口 memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); // 剪裁区大小 desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // 指定剪裁模式 desc.dwBackBufferCount = 1; // 后(页)备缓冲区的个数,默认为1个 desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX| DDSCAPS_FLIP; // 指定剪裁方法 // 建立主绘图页(也就是前页) result = m_pDD7->CreateSurface(&desc, &m_pPSur, NULL); if(result != DD_OK) { MessageBox(NULL, "建立主绘图页失败!", NULL, MB_OK); return false; } m_pPSur->SetClipper(lpDDclip); //设置剪裁(开始剪裁) // 连接后缓冲区(连上后,就可以进行翻页了) caps.dwCaps = DDSCAPS_BACKBUFFER; result = m_pPSur->GetAttachedSurface(&caps, &m_pBBuf); if(result != DD_OK) { MessageBox(NULL, "连接后缓冲区失败!", NULL, MB_OK); return false; } } else { // 窗口模式忽略,在MFC中可使用,但MFC不稳定,不推荐使用 result = m_pDD7->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); if(result != DD_OK) { MessageBox(NULL, "设定程序协调层级失败!", NULL, MB_OK); } DDSURFACEDESC2 desc; memset(&desc,0,sizeof(desc)); ZeroMemory(&desc,sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_CAPS ; // desc.dwBackBufferCount = 1; desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; result = m_pDD7->CreateSurface(&desc, &m_pPSur, NULL); if(result != DD_OK) { MessageBox(NULL, "建立主绘图页失败!", NULL, MB_OK); return false; } // 4.创建辅助图面 memset(&desc,0,sizeof(desc)); desc.dwSize=sizeof(desc); desc.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; desc.dwWidth =Width; desc.dwHeight=Height; result = m_pDD7->CreateSurface(&desc,&m_pBBuf,NULL); if (FAILED(result)) { MessageBox(NULL, "创建辅助图面失败!", NULL, MB_OK); return false; } // 3.创建裁剪 IDirectDrawClipper *lpClipper=NULL; result = m_pDD7->CreateClipper(NULL,&lpClipper,NULL); if (FAILED(result)) { MessageBox(NULL, "创建裁剪区域失败!", NULL, MB_OK); return false; } result = lpClipper->SetHWnd(0,hWnd); if (FAILED(result)) { MessageBox(NULL, "设置窗口裁剪区域失败!", NULL, MB_OK); return false; } result = m_pPSur->SetClipper(lpClipper); if (FAILED(result)) { MessageBox(NULL, "设置主图面的裁剪区域失败!", NULL, MB_OK); return false; } lpClipper->Release(); } return true; } bool CGraphic::InitOffScreen(LPDIRECTDRAWSURFACE7& oBuffer,DWORD dwWidth,DWORD dwHeight, bool b_ColorKey,DWORD color) { HRESULT result; memset(&desc,0,sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY ; desc.dwWidth = dwWidth; desc.dwHeight = dwHeight; result = m_pDD7->CreateSurface(&desc, &oBuffer, NULL); if(result != DD_OK ) { MessageBox(NULL, "建立幕后暂存区失败!", NULL,MB_OK); return false; } if(b_ColorKey) { DDColorKey(oBuffer,color); } return true; } bool CGraphic::LoadToOffScreen(LPDIRECTDRAWSURFACE7& oBuffer,DWORD dwWidth ,DWORD dwHeight, LPCSTR BitMapFile,bool b_ColorKey,DWORD color) { HDC m_hdc; //一个显示设备句柄 HDC m_hdcImage; //一个显示设备句柄 HBITMAP m_hBmp; BITMAP m_fBmp; DDSURFACEDESC2 ddsd; bool b_result; HRESULT result; m_hBmp = (HBITMAP)::LoadImage(NULL, BitMapFile, IMAGE_BITMAP, NULL, NULL , LR_LOADFROMFILE|LR_CREATEDIBSECTION); if(NULL == m_hBmp) { MessageBox(NULL, "读取位图失败!", NULL, MB_OK); return false; } GetObject(m_hBmp,sizeof(m_fBmp),&m_fBmp); //为图片分配内存空间 dwWidth = (dwWidth == 0 ? m_fBmp.bmWidth : dwWidth); dwHeight = (dwHeight == 0 ? m_fBmp.bmHeight : dwHeight); b_result = InitOffScreen(oBuffer,dwWidth,dwHeight,true,color); if( !b_result)//判断创建是否成功 { MessageBox(NULL, "创建离屏缓冲区失败!", NULL, MB_OK); return false; } m_hdcImage = ::CreateCompatibleDC(NULL); if (NULL == m_hdcImage) { MessageBox(NULL,"创建上下文设备出错!",NULL,MB_OK); return false; } SelectObject(m_hdcImage, m_hBmp); //GetObject(m_hBmp, sizeof(m_fBmp), &m_fBmp); ddsd.dwSize = sizeof(ddsd); oBuffer->GetSurfaceDesc(&ddsd); oBuffer->GetDC(&m_hdc); result = oBuffer->GetDC(&m_hdc); if( result != NULL) { StretchBlt(m_hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, m_hdcImage, 0, 0, m_fBmp.bmWidth, m_fBmp.bmHeight, SRCCOPY); oBuffer->ReleaseDC(m_hdc); } DeleteDC(m_hdcImage);//删除显示设备 if( NULL == result)//判断是否加载成功 { return false; } return true; } void CGraphic::BltBBuffer(LPDIRECTDRAWSURFACE7 oBuffer,bool b_ColorKey,int x, int y, int ClipX, int ClipY, int ClipEndX, int CLipEndY) { m_bRect.left = ClipX; m_bRect.top = ClipY; m_bRect.right = ClipEndX; m_bRect.bottom = CLipEndY; int nx=x, ny=y; m_rcRect.left = x; m_rcRect.top = y ; m_rcRect.right = x + ClipEndX - ClipX; m_rcRect.bottom = y + CLipEndY - ClipY; // 做相应地抠像,因为屏幕要移出去了。 if(x < 0) { m_bRect.left = m_bRect.left + abs(x); m_rcRect.left = 0; nx = 0; } else if(x + (ClipEndX-ClipX) >= int(m_dwWidth)) { m_bRect.right = m_bRect.right - (x + (ClipEndX-ClipX) - m_dwWidth); m_rcRect.right = m_dwWidth; } if(y < 0) { m_bRect.top = m_bRect.top + abs(y); m_rcRect.top = 0; ny = 0; } else if(y + (CLipEndY-ClipY) >= int(m_dwHeight)) { m_bRect.bottom = m_bRect.bottom - (y + (CLipEndY-ClipY) - m_dwHeight); m_rcRect.bottom = m_dwHeight; } if(b_ColorKey) { if(m_bfScreen) m_pBBuf->BltFast( nx, ny, oBuffer, &m_bRect, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY); else m_pBBuf->Blt(&m_rcRect, oBuffer, &m_bRect, DDBLT_KEYSRC|DDBLT_WAIT|DDBLTFAST_SRCCOLORKEY, NULL);//(&rct, surface, NULL, DDBLT_WAIT, NULL)); } else { if(m_bfScreen) m_pBBuf->BltFast( nx, ny, oBuffer, &m_bRect, DDBLTFAST_WAIT); else m_pBBuf->Blt(&m_rcRect, oBuffer, &m_bRect, (DDBLT_WAIT | DDBLT_KEYSRC), NULL); } } /* void CGraphic::CopyToBuffer(LPDIRECTDRAWSURFACE7& SrcBuffer,LPDIRECTDRAWSURFACE7& DestBuffer, bool b_ColorKey,int x,int y,RECT m_rect) { m_bRect = m_rect; if(b_ColorKey) { DestBuffer->BltFast( x, y, SrcBuffer, &m_bRect, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY); } else { DestBuffer->BltFast( x, y, SrcBuffer, &m_bRect, DDBLTFAST_WAIT); } } void CGraphic:: CopyToBuffer(LPDIRECTDRAWSURFACE7& SrcBuffer,LPDIRECTDRAWSURFACE7& DestBuffer, bool b_ColorKey,float zoomX, float zoomY) { HDC m_hdc; HDC m_hdcImage; int width = 0, height = 0; DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); SrcBuffer->GetSurfaceDesc(&ddsd); width = ddsd.dwWidth; height = ddsd.dwHeight; DestBuffer->GetSurfaceDesc(&ddsd); SrcBuffer->GetDC(&m_hdc); DestBuffer->GetDC(&m_hdcImage); int iOldMode = SetStretchBltMode(m_hdcImage, COLORONCOLOR); StretchBlt(m_hdcImage,0, 0, ddsd.dwWidth, ddsd.dwHeight, m_hdc ,0, 0, width, height, SRCCOPY); SetStretchBltMode(m_hdcImage, iOldMode); DestBuffer->ReleaseDC(m_hdcImage); SrcBuffer->ReleaseDC(m_hdc); } */ void CGraphic::Flip() { if(m_pPSur && m_pBBuf) { if (m_pPSur->IsLost() == DDERR_SURFACELOST)//判断前页是否丢失 { m_pPSur->Restore();//前页重绘 } if (m_pBBuf->IsLost() == DDERR_SURFACELOST)//判断后页是否丢失 { m_pBBuf->Restore();//后页重绘 } } RECT rect; GetWindowRect(m_hWnd, &rect); m_pPSur->Blt(&rect,m_pBBuf,NULL,DDBLT_WAIT,NULL); // m_pPSur->Flip(NULL, DDFLIP_WAIT); } /*void CGraphic::Flip(int x,int y, RECT m_rect) { if(m_pPSur && m_pBBuf) { if (m_pPSur->IsLost() == DDERR_SURFACELOST)//判断前页是否丢失 { m_pPSur->Restore();//前页重绘 } if (m_pBBuf->IsLost() == DDERR_SURFACELOST)//判断后页是否丢失 { m_pBBuf->Restore();//后页重绘 } } m_pPSur->BltFast(x,y,m_pBBuf,&m_rect,DDBLTFAST_WAIT); } */ //---------------------------------------------------------------------------------------- //Name: DDColorKey 设置镂空的颜色键码 //Desc: oBuffer 只是对那个缓冲区内进行镂空处理 // //---------------------------------------------------------------------------------------- void CGraphic::DDColorKey(LPDIRECTDRAWSURFACE7 oBuffer,DWORD color) { m_key.dwColorSpaceHighValue = color; m_key.dwColorSpaceLowValue = color; oBuffer->SetColorKey(DDCKEY_SRCBLT, &m_key); } void CGraphic::ClearBuffer(LPDIRECTDRAWSURFACE7& Buffer) { DDBLTFX ddBltFx; ddBltFx.dwSize=sizeof(DDBLTFX); ddBltFx.dwFillPixel=0; Buffer->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx); } //--鼠标拷贝判断 void CGraphic::SetMouseRect(RECT* m_rect, int scWidth, int scHeight, int msWidth, int msHeight) { int mouseX, mouseY; if(m_MPos.x > scWidth - msWidth) //--若鼠标越界则只设置出现在屏幕的区域 { mouseX = scWidth - m_MPos.x; } else //--否则就设置为传进来的图片区域大小 { mouseX = msWidth; } if(m_MPos.y > scHeight - msHeight) { mouseY = scHeight - m_MPos.y; } else { mouseY = msHeight; } SetRect(m_rect, 0, 0, mouseX, mouseY); } void CGraphic::OutText(LPCSTR str, int x, int y,COLORREF color) { HDC hdc; m_pBBuf->GetDC(&hdc); SetTextColor(hdc, color); //文字颜色 //SetBkColor(hdc, RGB(0, 0, 0)); //背景颜色 SetBkMode(hdc, TRANSPARENT); //背景透明 TextOut(hdc, x, y, str, strlen(str)); m_pBBuf->ReleaseDC(hdc); }
// GameTime.h: interface for the CGameTime class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GAMETIME_H__E21F4529_19F8_4F2E_8B0A_3BB627C8E0AE__INCLUDED_) #define AFX_GAMETIME_H__E21F4529_19F8_4F2E_8B0A_3BB627C8E0AE__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "head.h" class CGameTime { private: __int64 m_start; //开始的时间 __int64 m_end; //结束的时间 __int64 m_frequency; //计时器频 double m_time; //得到当前时间 public: CGameTime(); virtual ~CGameTime(); double GetTime(); }; #endif // !defined(AFX_GAMETIME_H__E21F4529_19F8_4F2E_8B0A_3BB627C8E0AE__INCLUDED_)
// GameTime.cpp: implementation of the CGameTime class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GameTime.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CGameTime::CGameTime() { QueryPerformanceFrequency((LARGE_INTEGER*)&m_frequency); } CGameTime::~CGameTime() { } double CGameTime::GetTime() { QueryPerformanceCounter((LARGE_INTEGER*)&m_start); m_time = (double)(m_start) / (double)m_frequency; //将时间转为以秒为单位 return m_time; }
#ifndef _HEADER #define _HEADER #include <windows.h> //-- windows函数中的头文件 #include <stdio.h> //-- c 语言的头文件 #include <ddraw.h> //-- DirectDraw的函数需要的头文件 //--对应函数调用所需要的静态连接库 #pragma comment (lib,"ddraw.lib") #pragma comment (lib,"dxguid.lib") #pragma comment (lib,"winmm.lib") #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) #define SafeRelease(x) if (x) { x->Release(); x=NULL; } #define WINDOWS_GAME_WIDTH 800 #define WINDOWS_GAME_HEIGHT 600 #endif