设计游戏菜单背景循环移动

演示程序下载地址:http://download.csdn.net/detail/jiangcaiyang123/4060455

程序的截图如下所示:


设计游戏菜单背景循环移动


DirectX的纹理很重要。就像一个人的脸一样。如果没有它,就好像人的脸上没有五官一样难看。所以要对于我们这些初学者来说,掌握纹理的处理就相当于了解相当部分的DirectX知识一样。这回我就利用上了DirectX中纹理的一些知识,来实现游戏中常常出现的菜单背景循环移动的场景。

要使用纹理,首先要学会载入纹理。我使用D3DXCreateTextureFromFileEx()这个函数。因为它可控制的参数多,可以达到很好的效果。欲了解此函数的参数,请查阅MSDN。载入了图片后,我使用其中的D3DXIMAGE_INFO的结构体来获得它的宽和高。获得了以后可以将该纹理平铺至屏幕上。这里假设屏幕的分辨率是640×480。

在载入了纹理之后,使用自定义的顶点格式。该格式的定义如下:
struct STVertex// 定义自己的顶点结构体
{
float x, y, z;// 纹理坐标位置
float u, v; // 纹理坐标内的位置
}
其中控制纹理的平铺则使用的是U和V这两个变量。那么接下来我就在渲染的过程中改变这两个变量,获得循环移动的效果。在U和V处于0以下或者是1.0以上的范围,它的渲染行为通常是不固定的。但是DirectX内部默认的是平铺的效果。也可以改变其为镜面平铺、不渲染的效果(参见《Real Time Rendering》丛书)。我们不必更改,使用默认平铺效果即可。
最后设置灵活顶点格式(FVF),设置顶点流的源,和使用DrawPrimitive来绘制图形。

以下是程序的部分代码:

// BackgroundMove.cpp 实现文件

#include "BackgroundMove.h"

CBackgroundMove::CBackgroundMove( HINSTANCE hInst, HWND hWnd, LPDIRECT3DDEVICE9 pDevice, int width, int height )		// 构造函数
{
	// 成员赋值
	m_pDevice			= pDevice;
	m_TexOffsetX		= 0.0f;
	m_TexOffsetY		= 0.0f;
	m_MoveSpeedX		= 0.005f;
	m_MoveSpeedY		= 0.02f;
	
	// 初始化输入系统
	m_ImmediateInput.Initialize( IMMEDIATE, hInst, hWnd );
	m_BufferInput.Initialize( BUFFERED, hInst, hWnd );
	
	// 设置视角范围
	SetViewport( width, height );
	
	// 初始化顶点
	InitializeVertices( );
	
	// 设置纹理
	SetTexture( width, height ); 
}

void CBackgroundMove::SetViewport( int width, int height )		// 设置视角
{
	ZeroMemory( &m_Viewport, sizeof( m_Viewport ) );// 清零
	
	m_Viewport.X				= 0;
	m_Viewport.Y				= 0;
	m_Viewport.Width			= width;
	m_Viewport.Height			= height;
	m_Viewport.MinZ				= 0.0f;
	m_Viewport.MaxZ				= 1.0f;
	
	m_pDevice->SetViewport( &m_Viewport );
} 

void CBackgroundMove::Draw( void )								// 绘图
{
	m_pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );				// 绘图函数
	
	// 开始交互
	m_ImmediateInput.UpdateKeyState( );
	if ( m_ImmediateInput.KeyDown( DIK_UP ) )
	{
		m_pVertices[1].y += 0.05f;
		m_pVertices[3].y += 0.05f;
	}
	if ( m_ImmediateInput.KeyDown( DIK_DOWN ) )
	{
		m_pVertices[1].y -= 0.05f;
		m_pVertices[3].y -= 0.05f;
	}
	// 调整移动速率的
	if ( m_ImmediateInput.KeyDown( DIK_D ) )
	{
		m_MoveSpeedX += 0.005f;
	}
	if ( m_ImmediateInput.KeyDown( DIK_A ) )
	{
		m_MoveSpeedX -= 0.005f;
	}
	if ( m_ImmediateInput.KeyDown( DIK_W ) )
	{
		m_MoveSpeedY += 0.005f;
	}
	if ( m_ImmediateInput.KeyDown( DIK_S ) )
	{
		m_MoveSpeedY -= 0.005f;
	}
	
	// 纹理的背景自动移动
	int i;
	for ( i = 0; i < 4; i++ )
	{
		m_pVertices[i].u += m_MoveSpeedX;
		m_pVertices[i].v += m_MoveSpeedY;
	}
} 

unsigned long CBackgroundMove::Release( void )					// 释放空间
{
	if ( m_pBuffer != 0 )
	{
		m_pBuffer->Release( );
		m_pBuffer = 0;
	}
	if ( m_pTexture != 0 )
	{
		m_pBuffer->Release( );
		m_pBuffer = 0;
	}
	m_ImmediateInput.Release( );
	m_BufferInput.Release( );
	return 0;
}

void CBackgroundMove::InitializeVertices( void )				// 初始化顶点
{
	// 创建顶点缓存
	HRESULT hr;
	hr = m_pDevice->CreateVertexBuffer( 4 * sizeof( STVertex ), D3DUSAGE_WRITEONLY,
		TEXTURE_FVF, D3DPOOL_MANAGED, &m_pBuffer, NULL );
	ThrowIfFailed( hr, "不会吧,这都无法创建顶点缓存。⊙﹏⊙b汗" );
	
	hr = m_pBuffer->Lock( 0, 4 * sizeof( STVertex ), (void**)&m_pVertices, D3DLOCK_DISCARD );
	ThrowIfFailed( hr, "不可能,顶点怎么会锁住失败呢??o(>﹏<)o" );
	hr = m_pBuffer->Unlock( );
	ThrowIfFailed( hr, "不可能,顶点怎么会也会解锁失败呢??o(>﹏<)o" );
	
	// 设置顶点缓存和灵活顶点格式
	m_pDevice->SetStreamSource( 0, m_pBuffer, 0, sizeof( STVertex ) );	// 相同资源的顶点缓存要在一起为好
	m_pDevice->SetFVF( TEXTURE_FVF ); 
}

void CBackgroundMove::SetTexture( int width, int height )		// 设置纹理
{
	// 载入纹理
	D3DXIMAGE_INFO imageInfo;
	HRESULT hr;
 	hr = D3DXCreateTextureFromFileEx(							// 从文件创建纹理
			m_pDevice,								// DIRECT3DDEVICE9结构指针
			TEXT( "试验图片.png" ),					// 载入的图像文件名
			D3DX_DEFAULT,							// 宽
			D3DX_DEFAULT,							// 高
			D3DX_FROM_FILE,							// mip级别
			0,										// 用途
			D3DFMT_A8R8G8B8,						// 格式
			D3DPOOL_MANAGED,						// 内存池格式
			D3DX_DEFAULT,							// 滤波器
			D3DX_DEFAULT,							// mip滤波器
			0,										// 关键色(作掩码用)
			&imageInfo,								// 源文件信息
			NULL,									// 调色板
			&m_pTexture );							// IDirect3DTexture9指针
				
	ThrowIfFailed( hr, "不可能,载入纹理竟然会失败!是不是文件名错误了呢?" );
	
	// 设置顶点
	float			nU, nV;
	nU = float( width ) / float( imageInfo.Width ), nV = float( height ) / float( imageInfo.Height );
	m_pVertices[0].Set( -1.0f, -1.0f, 1.0f, m_TexOffsetX, m_TexOffsetY + nV );
	m_pVertices[1].Set( -1.0f, 1.0f, 1.0f, m_TexOffsetX, m_TexOffsetY );
	m_pVertices[2].Set( 1.0f, -1.0f, 1.0f, m_TexOffsetX + nU, m_TexOffsetY + nV );
	m_pVertices[3].Set( 1.0f, 1.0f, 1.0f, m_TexOffsetX + nU, m_TexOffsetY );
	
	// 设置关灯 
	hr = m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	ThrowIfFailed( hr, "怎么不能关灯了呢?" );
	
	// 设置纹理 
	hr = m_pDevice->SetTexture( 0, m_pTexture );
	ThrowIfFailed( hr, "不可能啊,设置纹理竟然错误?" );
}
	


程序的截图如下所示:


你可能感兴趣的:(设计游戏菜单背景循环移动)