用DirectX设计游戏主角运动
今天工作了一整天,就是在弄这个。DirectX的强大之处多得是,只要你肯发掘。像今天我就弄了一个让主角运动的程序,自己还制作了动画呢。画得不好请见谅啊。
程序呢,就是将sprite类简单地封装了一下,变得更加易用。但是遗憾的是,我还没有实现主角的跳跃。怎么办呢?只好再奋斗一天了。
程序是载入八个图像,然后每次显示不同的图像,这样主角的运动就显示出来啦。这就是我动画的奥秘。虽然这个类还有些成员函数是空的,但是总体来说,我对这个自己编写的类还是满意的。因为它有点继承了DIrectX库的特点,这样也比较易用。我会以这个程序为经验,下次开发出更好的程序的。
这是我的PlayerAction.h文件。
- /*---------------------------------------------------------------------------
- 蒋轶民制作 E-mail:jiangcaiyang123@163.com
- 文件名:PlayerAction.h
- 作用:让主角运动的实现
- ----------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- // 条件编译
- #ifndef _PLAYERACTION_H_
- #define _PLAYERACTION_H_
- // 定义的宏
- #define SPRITE_WIDTH 50
- #define SPRITE_HEIGHT 50
- // 将主角这个类封装起来
- class JPlayer
- {
- public:
- JPlayer():xPos(WINDOW_WIDTH*0.5f),yPos(WINDOW_HEIGHT-100),
- pPlayerSprite(0),pPlayerTexture(0)
- { spriteRect.top = 0; }//默认构造函数
- ~JPlayer(){}// 默认析构函数
- bool Initialize( void );// 初始化主角
- bool GoLeft( void );// 向左走
- bool GoRight( void );// 向右走
- bool Jump( void );// 跳跃
- bool Display( void );// 显示主角
- void Release( void );// 释放空间
- private:
- float xPos, yPos;// 主角的横纵坐标的位置
- RECT spriteRect;// 精灵动画的矩形框
- LPD3DXSPRITE pPlayerSprite;// 主角的子图形指针
- LPDIRECT3DTEXTURE9 pPlayerTexture;// 主角的图像纹理指针
- };
- typedef JPlayer* LPJPLAYER;// 定义主角的指针类型
- /*--------------------------------------------------------------------------*/
- // 初始化主角
- bool JPlayer::Initialize( void )
- {
- // 载入纹理图像并使用双线性滤波
- if ( FAILED ( D3DXCreateTextureFromFileEx( g_JDevice, "蘑菇(合图).png",
- 200, // 我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。
- 100, // 我不得不手动设置。D3DPOOL_DEFAULT在纹理中起作用,但是应用在D3DXSPRITE中会产生问题。
- 1, // 不要创建mip-map。它在子图形动画中会抛弃像素数学计算
- D3DPOOL_DEFAULT,
- D3DFMT_UNKNOWN,
- D3DPOOL_DEFAULT,
- D3DX_DEFAULT,
- D3DX_DEFAULT,
- D3DCOLOR_XRGB( 0, 0, 0 ),
- NULL,
- NULL,
- &pPlayerTexture ) ) )
- return false;
- g_JDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
- g_JDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
- // 设置三角形的背面不被剔除
- g_JDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
- // 创建子图形
- if ( FAILED( D3DXCreateSprite( g_JDevice, &pPlayerSprite ) ) )
- return false;
- return true;
- }
- /*--------------------------------------------------------------------------*/
- // 向左走
- bool JPlayer::GoLeft( void )
- {
- xPos -= 4.0f;
- spriteRect.top = 0;
- return true;
- }
- /*--------------------------------------------------------------------------*/
- // 向右走
- bool JPlayer::GoRight( void )
- {
- xPos += 4.0f;
- spriteRect.top = 50;
- return true;
- }
- /*--------------------------------------------------------------------------*/
- // 跳跃
- bool JPlayer::Jump( void )
- {
- return true;
- }
- /*--------------------------------------------------------------------------*/
- // 显示主角
- bool JPlayer::Display( void )
- {
- // 碰撞检测
- if ( xPos < 0.0f )
- xPos = 0.0f;
- else if ( xPos > WINDOW_WIDTH - SPRITE_WIDTH )
- xPos = WINDOW_WIDTH - SPRITE_WIDTH;
- // 显示每一个子图形
- static float frame = 0;
- spriteRect.left = (long)floor( frame ) * 50;
- spriteRect.bottom = spriteRect.top + 50;
- spriteRect.right = spriteRect.left + 50;
- frame += 0.05f;
- if ( frame >= 4.0f ) frame = 0.0f;
- // 设置D3DXVECTOR3结构体,在D3DXSPRITE::Draw函数中有应用
- D3DXVECTOR3 vCenter( 0.0f, 0.0f, 0.0f );
- D3DXVECTOR3 vPosition( xPos, yPos, 0.0f );
- // 渲染Sprite
- pPlayerSprite->Begin( D3DXSPRITE_ALPHABLEND );// 以Alpha混合形式进行渲染
- pPlayerSprite->Draw( pPlayerTexture, &spriteRect, &vCenter, &vPosition,
- D3DCOLOR_XRGB( 255, 255, 255 ) );
- pPlayerSprite->End();// 结束渲染
- return true;
- }
- /*--------------------------------------------------------------------------*/
- // 释放空间
- void JPlayer::Release( void )
- {
- if ( pPlayerSprite ) pPlayerSprite->Release(); pPlayerSprite = NULL;
- if ( pPlayerTexture ) pPlayerTexture->Release(); pPlayerTexture = NULL;
- }
- /*--------------------------------------------------------------------------*/
- #endif
下面是我的MainFrame.h文件:
- /*---------------------------------------------------------------------------
- 蒋轶民制作 E-mail:jiangcaiyang123@163.com
- 文件名:MainFrame.cpp
- 作用:设计主角移动的主框架
- ----------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- // 头文件
- #include<windows.h>
- #include<d3d9.h>
- #include<d3dx9.h>
- #include<stdio.h>
- // 库文件
- #pragma comment( lib, "d3d9.lib")
- #pragma comment( lib, "d3dx9.lib")
- // 定义的宏
- #define JCLASSNAME "优化的程序"
- #define JCAPTION "程序演示"
- #define FULLSCREEN FALSE// 全屏非全屏的标识符
- #define SAFE_RELEASE( p ) if ( p ) p->Release(); p = NULL;
- // 调整编译器设置
- #pragma warning( disable: 4100 )
- #if FULLSCREEN // 全屏非全屏的设置
- #define WINDOW_WIDTH 640
- #define WINDOW_HEIGHT 480
- #define WINDOW_STYLE WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE
- #else
- #define WINDOW_WIDTH 320
- #define WINDOW_HEIGHT 320
- #define WINDOW_STYLE WS_CAPTION | WS_SYSMENU
- #endif
- /*----------------------------------------------------------------------------*/
- // 全局变量
- LPDIRECT3D9 g_JD3D = NULL;// D3D结构体
- LPDIRECT3DDEVICE9 g_JDevice = NULL;// D3D装置结构体
- LPD3DXFONT g_FPSFont = NULL;// 指向FPS字体的指针
- RECT g_FPSFontPos = { WINDOW_WIDTH - 100, WINDOW_HEIGHT - 15,
- WINDOW_WIDTH, WINDOW_HEIGHT};// FPS所在的矩形框
- INT g_FrameCount = 0;// 帧的计数器
- INT g_lastTime = 0;// 记录上一秒的时间
- INT g_currentTime = 0;// 记录当前的时间
- CHAR g_FPSstr[25] = { 0 };// 记录当前帧率的字符串
- IDirect3DSurface9* g_surface = NULL;// 平面的指针
- /*----------------------------------------------------------------------------*/
- // 让主角运动的实现的头文件
- #include "PlayerAction.h"
- // 额外的全局变量
- LPJPLAYER g_JPlayer;// 包含主角这个类的指针
- /*----------------------------------------------------------------------------*/
- // 函数的声明
- BOOL InitializeD3D( HWND hWnd )
- {
- D3DDISPLAYMODE displayMode;
- //创建D3D对象
- g_JD3D = Direct3DCreate9( D3D_SDK_VERSION );
- if ( g_JD3D == NULL )
- return FALSE;
- // 获取显示器的模式
- if ( FAILED( g_JD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &displayMode ) ) )
- return FALSE;
- // D3D显示的参数
- D3DPRESENT_PARAMETERS jd3dpp;
- ZeroMemory( &jd3dpp, sizeof( jd3dpp ) );
- // 初始化D3DPRESENT_PARAMETERS
- jd3dpp.Windowed = !FULLSCREEN;
- jd3dpp.BackBufferWidth = WINDOW_WIDTH;
- jd3dpp.BackBufferHeight = WINDOW_HEIGHT;
- jd3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- jd3dpp.BackBufferFormat = displayMode.Format;
- jd3dpp.EnableAutoDepthStencil = TRUE;
- jd3dpp.AutoDepthStencilFormat = D3DFMT_D16;
- // 创建设备
- if(FAILED( g_JD3D->CreateDevice( D3DADAPTER_DEFAULT,
- D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &jd3dpp, &g_JDevice ) ) )
- return FALSE;
- // 设置渲染状态
- g_JDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
- g_JDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
- // 创建字体
- if ( FAILED( D3DXCreateFont( g_JDevice, 15, 0, 1, 1, 0, DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
- "Impact", &g_FPSFont ) ) ) return FALSE;
- // 创建离屏平面
- if ( FAILED ( g_JDevice->CreateOffscreenPlainSurface( WINDOW_WIDTH, WINDOW_HEIGHT,
- D3DFMT_X8R8G8B8, // 平面格式
- D3DPOOL_DEFAULT, // 内存池格式
- &g_surface, // 保存结果的缓存
- NULL) ) ) // 保留参数
- return FALSE;
- // 载入背景平面图像
- if ( FAILED( D3DXLoadSurfaceFromFile( g_surface, NULL, NULL, "背景图案.tga",
- NULL, D3DX_DEFAULT, 0, NULL ) ) ) return FALSE;
- // 初始化主角
- g_JPlayer = new JPlayer;
- g_JPlayer->Initialize();
- return TRUE;
- }
- /*----------------------------------------------------------------------------*/
- // 释放所有资源
- void ReleaseMemory( void )
- {
- SAFE_RELEASE( g_JD3D );
- SAFE_RELEASE( g_JDevice );
- SAFE_RELEASE( g_FPSFont );
- SAFE_RELEASE( g_surface );
- SAFE_RELEASE( g_JPlayer );// 释放JPlayer所占的内存
- }
- /*----------------------------------------------------------------------------*/
- // 渲染屏幕
- void RenderScene( void )
- {
- // 计数器开始计数(以毫秒计)
- g_currentTime = GetTickCount();
- if ( g_currentTime - g_lastTime > 1000 )
- {
- sprintf_s( g_FPSstr, 25, "当前FPS:%d", g_FrameCount );
- g_lastTime = g_currentTime;
- g_FrameCount = 0;
- }
- else g_FrameCount++;
- g_JDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
- D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0);// 清除屏幕
- // 载入背景平面图像
- IDirect3DSurface9* backbuffer = NULL;
- g_JDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO,
- &backbuffer );// 获取后台缓存
- g_JDevice->StretchRect( g_surface, NULL,
- backbuffer, NULL, D3DTEXF_NONE );// 将后台矩形放入前景矩形
- // 开始渲染
- g_JDevice->BeginScene();
- g_JPlayer->Display();// 显示主角
- g_FPSFont->DrawText( NULL, g_FPSstr, -1, &g_FPSFontPos, DT_CENTER,
- D3DCOLOR_XRGB( 0, 0, 0 ) );// 显示字体
- // 结束渲染
- g_JDevice->EndScene();
- g_JDevice->Present( NULL, NULL, NULL, NULL );
- }
- /*----------------------------------------------------------------------------*/
- // 回调函数,用来处理消息
- HRESULT CALLBACK MyAppProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- if ( g_JPlayer == NULL )
- return (HRESULT)DefWindowProc( hWnd, msg, wParam, lParam );
- switch ( msg )
- {
- case WM_DESTROY:
- PostQuitMessage( 0 ); break;
- case WM_KEYDOWN:
- if ( wParam == VK_ESCAPE ) PostQuitMessage( 0 );
- if ( wParam == VK_LEFT ) g_JPlayer->GoLeft();
- if ( wParam == VK_RIGHT ) g_JPlayer->GoRight();
- break;
- case WM_KEYUP: break;
- default: break;
- }
- return (HRESULT)DefWindowProc( hWnd, msg, wParam, lParam );
- };
- /*----------------------------------------------------------------------------*/
- // 程序的入口,主函数
- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmd, INT show )
- {
- // 设置Window Class结构并且注册它
- WNDCLASSEX jWndCls = { sizeof( jWndCls ), CS_CLASSDC, MyAppProc, 0L, 0L, hInst,
- NULL, LoadCursor( NULL, IDC_ARROW) , 0, NULL, JCLASSNAME, NULL };
- RegisterClassEx( &jWndCls );
- // 设置窗口并且显示窗口
- HWND hWnd = CreateWindow( JCLASSNAME, JCAPTION, WINDOW_STYLE, 100, 40,
- WINDOW_WIDTH, WINDOW_HEIGHT, GetDesktopWindow(), NULL, jWndCls.hInstance, NULL);
- if ( hWnd == NULL )
- return FALSE;
- ShowWindow( hWnd, SW_SHOWDEFAULT );
- UpdateWindow( hWnd );
- // 初始化设置
- if ( InitializeD3D( hWnd ) == FALSE )
- return FALSE;
- // 进入消息循环
- MSG msg;
- ZeroMemory( &msg, sizeof( msg ) );
- while( msg.message != WM_QUIT )
- {
- if ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
- {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- else
- {
- // 渲染屏幕
- RenderScene();
- }
- }
- // 程序结束,释放内存所有资源
- ReleaseMemory();
- // 解除窗口注册
- UnregisterClass( JCLASSNAME, jWndCls.hInstance );
- return ( INT ) msg.wParam;
- }
程序需要载入背景图和纹理图,分别如下:
程序的动态显示如下:
我的更多DirectX文章:
使用DirectX让进行Alpha混合的子图形移动(精灵动画)
设计DirectX游戏开头动画效果设计DirectX游戏开头画面淡入淡出的效果
怎么样?这个和我心目中的游戏还差得远呢。以后要做比这个更加强大的游戏!!!