本篇是创建游戏内核(10)【接口与实现分离版】的续篇,关于该内核的细节说明请参考创建游戏内核(11),这个版本主要是按照功能划分模块的思想,并严格按照接口与实现相分离的原则来写的,没有用面向对象的思想来写,没有继承没有多态。大家可以对比两个版本,比较优劣。
接口:
BOOL create_vertex_buffer(LPDIRECT3DVERTEXBUFFER9* vertex_buffer,
ulong num_vertices, ulong vertex_size, DWORD fvf);
BOOL copy_vertex_buffer(LPDIRECT3DVERTEXBUFFER9 vertex_buffer,
ulong first_vertex, ulong num_vertices,
void* vertex_list);
BOOL render_vertex_buffer(LPDIRECT3DVERTEXBUFFER9 vertex_buffer,
ulong first_vertex, ulong num_primitives, DWORD primitive_type);
ulong get_vertex_size(LPDIRECT3DVERTEXBUFFER9 vertex_buffer);
DWORD get_vertex_fvf(LPDIRECT3DVERTEXBUFFER9 vertex_buffer);
实现:
//---------------------------------------------------------------------------
// create vertex buffer.
//---------------------------------------------------------------------------
BOOL create_vertex_buffer(LPDIRECT3DVERTEXBUFFER9* vertex_buffer,
ulong num_vertices, ulong vertex_size, DWORD fvf)
{
// check condition
if(g_d3d_device == NULL)
return FALSE;
if(FAILED(g_d3d_device->CreateVertexBuffer(num_vertices * vertex_size, 0, fvf, D3DPOOL_MANAGED,
vertex_buffer, NULL)))
{
return FALSE;
}
return TRUE;
}
//---------------------------------------------------------------------------
// copy vertex data from VertexList to vertex buffer.
//---------------------------------------------------------------------------
BOOL copy_vertex_buffer(LPDIRECT3DVERTEXBUFFER9 vertex_buffer,
ulong first_vertex, ulong num_vertices,
void* vertex_list)
{
// check condition first
if(g_d3d_device == NULL)
return FALSE;
ulong _vertex_size = get_vertex_size(vertex_buffer);
ulong vertex_total_size = num_vertices * _vertex_size;
char* _ptr;
// locks a range of vertex data and obtains a pointer to the vertex buffer memory
if(FAILED(vertex_buffer->Lock(first_vertex * _vertex_size, vertex_total_size, (void**) &_ptr, 0)))
return FALSE;
// copy vertices to vertex buffer
memcpy(_ptr, vertex_list, vertex_total_size);
// unlock vertex buffer
if(FAILED(vertex_buffer->Unlock()))
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
// render vertex buffer into display.
//---------------------------------------------------------------------------
BOOL render_vertex_buffer(LPDIRECT3DVERTEXBUFFER9 vertex_buffer,
ulong first_vertex, ulong num_primitives, DWORD primitive_type)
{
if(g_d3d_device == NULL || vertex_buffer == NULL)
return FALSE;
ulong _vertex_size = get_vertex_size(vertex_buffer);
// binds a vertex buffer to a device data stream
g_d3d_device->SetStreamSource(0, vertex_buffer, 0, _vertex_size);
DWORD _fvf = get_vertex_fvf(vertex_buffer);
// sets the current vertex stream declaration
g_d3d_device->SetFVF(_fvf);
// Renders a sequence of nonindexed, geometric primitives of the specified type from the current set
// of data input streams.
g_d3d_device->DrawPrimitive((D3DPRIMITIVETYPE) primitive_type, first_vertex, num_primitives);
return TRUE;
}
//---------------------------------------------------------------------------
// Return the size of a vertex for a flexible vertex format (FVF)
//---------------------------------------------------------------------------
ulong get_vertex_size(LPDIRECT3DVERTEXBUFFER9 vertex_buffer)
{
D3DVERTEXBUFFER_DESC _buffer_desc;
vertex_buffer->GetDesc(&_buffer_desc);
return D3DXGetFVFVertexSize(_buffer_desc.FVF);
}
//---------------------------------------------------------------------------
// Return vertex flexible format.
//---------------------------------------------------------------------------
DWORD get_vertex_fvf(LPDIRECT3DVERTEXBUFFER9 vertex_buffer)
{
D3DVERTEXBUFFER_DESC _buffer_desc;
vertex_buffer->GetDesc(&_buffer_desc);
return _buffer_desc.FVF;
}
测试代码:
/***********************************************************************************
PURPOSE:
Test for vertex buffer function.
***********************************************************************************/
#include <windows.h>
#include "core_framework.h"
#include "core_graphics.h"
#include "core_tool.h"
// The 2D vertex format and descriptor
typedef struct
{
float x, y, z; // 2D coordinates
float rhw; // rhw
D3DCOLOR diffuse; // diffuse color component
} VERTEX;
#define VERTEX_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
IDirect3DVertexBuffer9* g_vertex_buffer;
IDirect3DTexture9* g_texture;
//--------------------------------------------------------------------------------
// Initialize data for game.
//--------------------------------------------------------------------------------
BOOL game_init()
{
// initialize vertex data
VERTEX _verts[] = {
{ 100.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 300.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 100.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 300.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0,64,128,255) },
{ 50.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) },
{ 350.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) },
{ 50.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) },
{ 350.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128,0,0,128) }
};
// Create Direct3D and Direct3DDevice object
if(! create_display(g_hwnd, get_window_width(g_hwnd), get_window_height(g_hwnd), 16, TRUE, FALSE))
return FALSE;
create_vertex_buffer(&g_vertex_buffer, sizeof(_verts), sizeof(VERTEX), VERTEX_FVF);
copy_vertex_buffer(g_vertex_buffer, 0, 8, _verts);
return TRUE;
}
//--------------------------------------------------------------------------------
// Render every game frame.
//--------------------------------------------------------------------------------
BOOL game_frame()
{
clear_display_buffer(D3DCOLOR_RGBA(0, 0, 0, 255));
if(SUCCEEDED(g_d3d_device->BeginScene()))
{
enalbe_alpha_blending(FALSE, 0, 0);
render_vertex_buffer(g_vertex_buffer, 0, 2, D3DPT_TRIANGLESTRIP);
enalbe_alpha_blending(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
render_vertex_buffer(g_vertex_buffer, 4, 2, D3DPT_TRIANGLESTRIP);
g_d3d_device->EndScene();
}
present_display();
return TRUE;
}
//--------------------------------------------------------------------------------
// Release all game resources.
//--------------------------------------------------------------------------------
BOOL game_shutdown()
{
release_com(g_vertex_buffer);
release_com(g_d3d_device);
release_com(g_d3d);
return TRUE;
}
//--------------------------------------------------------------------------------
// Main function, routine entry.
//--------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE inst, HINSTANCE pre_inst, LPSTR cmd_line, int cmd_show)
{
if(! build_window(inst, "MainClass", "MainWindow", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480))
return FALSE;
run_game(game_init, game_frame, game_shutdown);
return 0;
}
点击下载源码和工程
程序截图: