// 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