c++第一人称相机在directx

c++ first person camera in directx

本文关键字:directx 相机 第一人称 c++      更新时间:2023-10-16

我是一名初级程序员,我正在创建一个项目,允许我通过第一人称相机在房间里走动,到目前为止,我已经绘制了建筑物等,但现在我卡住了,不知道如何制作第一人称相机,让我走动,谁能给我指一个相机类,我可以使用或一些有用的代码?提前感谢

下面的

是我的一个建筑的代码,但不是我的完整项目,它是旋转的,所以我可以看到我画的是什么。我希望能够使用方向键向前和向后移动,也可以向左和向右移动:)

#include <stdio.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dinput.h>
#include <math.h>
const char TITLE[] = "game experimenting";

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
//*****Direct 3D Initialization*****
LPDIRECT3D9             g_pD3D       = NULL; 
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; 
// Buffer to hold vertices
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; 
//Direct Input References
LPDIRECTINPUT8 m_pDIObject = NULL;//DirectInput object
LPDIRECTINPUTDEVICE8 m_pDIKeyboardDevice = NULL;//keyboard device
LPDIRECTINPUTDEVICE8 m_pDIMouseDevice = NULL;//mouse device
LPDIRECTINPUTDEVICE8 m_pDIJoystickDevice = NULL;//joystick device
//D3DXMATRIX Transformation Matrices
D3DXMATRIX g_matProj;
D3DXMATRIX g_matView;
D3DXMATRIX g_matWorld;
//**********************
//****** Vertex Buffer Definition and Setting ***
struct CUSTOMVERTEX
{
    FLOAT x, y, z; // The position for the vertex
    DWORD color;        // The vertex color
};

int numberOfTriangles = 34;
int numberOfVertecies = 3*numberOfTriangles;
float scale = 1.0f;
float doorHeight = 1.0f;
float doorWidth = 0.25f;
CUSTOMVERTEX g_Vertices[] =
{
    // Y +Axis 
    //Top Side Outer Wall
    { 1.0f, 1.0f,-1.0f, 0xffffffff, }, 
    { 1.0f, 1.0f,1.0f,  0xffffffff, }, 
    { -1.0f,1.0f, -1.0f, 0xffffffff,}, //Triangle 
    { -1.0f,1.0f, 1.0f, 0xffffffff,}, 
    { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
    { -1.0f,1.0f, -1.0f, 0xffffffff,}, //Triangle 
    //Top Side Inner Wall
    { 0.9f, 0.9f,-0.9f, 0x00ff0000, }, 
    { 0.9f, 0.9f,0.9f,  0x00ff0000, }, 
    { -0.9f,0.9f, -0.9f, 0x00ff0000,}, //Triangle 
    { -0.9f,0.9f, 0.9f, 0x00ff0000,}, 
    { 0.9f, 0.9f, 0.9f, 0x00ff0000, }, 
    { -0.9f,0.9f, -0.9f, 0x00ff0000,}, //Triangle 
    // X +Axis 
    //Right Side Outer Wall
    { 1.0f, 1.0f,-1.0f, 0xffffffff, }, 
    { 1.0f, 1.0f,1.0f,  0xffffffff, }, 
    { 1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
    { 1.0f,-1.0f, 1.0f, 0xffffffff,}, 
    { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
    { 1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
    //Right Side Inner Wall
    { 0.9f, 0.9f,-0.9f, 0xff0000ff, }, 
    { 0.9f, 0.9f,0.9f,  0xff0000ff, }, 
    { 0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
    { 0.9f,-1.0f, 0.9f, 0xff0000ff,}, 
    { 0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
    { 0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
    // X -Axis 
    //Left Side Outer Wall
    {-1.0f, 1.0f,-1.0f, 0xffffffff, }, 
    {-1.0f, 1.0f,1.0f,  0xffffffff, }, 
    {-1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
    {-1.0f,-1.0f, 1.0f, 0xffffffff,}, 
    {-1.0f, 1.0f, 1.0f, 0xffffffff, }, 
    {-1.0f,-1.0f, -1.0f, 0xffffffff,}, /////Triangle 
    //Left Side Inner Wall
    {-0.9f, 0.9f,-0.9f, 0xff0000ff, }, 
    {-0.9f, 0.9f,0.9f,  0xff0000ff, }, 
    {-0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
    {-0.9f,-1.0f, 0.9f, 0xff0000ff,}, 
    {-0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
    {-0.9f,-1.0f, -0.9f, 0xff0000ff,}, /////Triangle 
    // Z +Axis  
    //Back Outer Wall
    { 1.0f,-1.0f, 1.0f, 0xffffffff, }, 
    { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
    { -1.0f,-1.0f, 1.0f, 0xffffffff,}, /////Triangle 
    { -1.0f,1.0f, 1.0f, 0xffffffff,}, 
    { 1.0f, 1.0f, 1.0f, 0xffffffff, }, 
    { -1.0f,-1.0f, 1.0f, 0xffffffff,}, /////Triangle 
    //Back Inner Wall
    { 0.9f,-1.0f, 0.9f, 0xff0000ff, }, 
    { 0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
    { -0.9f,-1.0f, 0.9f, 0xff0000ff,}, /////Triangle 
    { -0.9f,0.9f, 0.9f, 0xff0000ff,}, 
    { 0.9f, 0.9f, 0.9f, 0xff0000ff, }, 
    { -0.9f,-1.0f, 0.9f, 0xff0000ff,}, /////Triangle 
    // Z Negative Axis 
    //Front Outer Wall Top1
    { 1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff, }, 
    { 1.0f, 1.0f, -1.0f, 0xffffffff, }, 
    { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle 
    //Front Outer Wall Top2
    { -1.0f, 1.0f, -1.0f, 0xffffffff, }, 
    { 1.0f, 1.0f, -1.0f, 0xffffffff, }, 
    { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle 
    //Front Outer Wall Left1
    { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
    { -1.0f,-1.0f, -1.0f, 0xffffffff,}, 
    { -1.0f+(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, /////Triangle
    //Front Outer Wall Left2
    { -1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
    { -1.0f+(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, 
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle
    //Front Outer Wall Right1
    { 1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
    { 1.0f,-1.0f, -1.0f, 0xffffffff,}, 
    { 1.0f-(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, /////Triangle
    //Front Outer Wall Right2
    { 1.0f,-1.0f+doorHeight, -1.0f, 0xffffffff,}, 
    { 1.0f-(scale-doorWidth),-1.0f, -1.0f, 0xffffffff,}, 
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffffffff,}, /////Triangle
    //Door Inner Edges Right of door 1
    { 1.0f-(scale-doorWidth),-1.0f, -1.0f, 0xffff0099,}, 
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
    { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
    //Door Inner Edges Right of door 2
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, 
    { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
    //Door Inner Edges Left of door 1
    { -1.0f+(scale-doorWidth),-1.0f, -1.0f, 0xffff0099,}, 
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
    { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
    //Door Inner Edges Left of door 2
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,},
    { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xffff0099,}, /////Triangle
    //Door Inner Edges Top Of Door 1
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,},
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,}, 
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, /////Triangle
    //Door Inner Edges Top Of Door 2
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, 
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -1.0f, 0xffff0099,},
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xffff0099,}, /////Triangle
    //FRONT Inner Wall Top1
    { 0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff, }, 
    { 0.9f, 1.0f, -0.9f, 0xff0000ff, }, 
    { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, /////Triangle 
    //FRONT Inner Wall Top2
    { -0.9f, 1.0f, -0.9f, 0xff0000ff, }, 
    { 0.9f, 1.0f, -0.9f, 0xff0000ff, }, 
    { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, /////Triangle 
    //FRONT Inner Wall Left1
    { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, 
    { -0.9f,-1.0f, -0.9f, 0xff0000ff,}, 
    { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xff0000ff,}, /////Triangle
    //FRONT Inner Wall Left2
    { -0.9f,-1.0f+doorHeight, -0.9f, 0xff0ff0ff,}, 
    { -1.0f+(scale-doorWidth),-1.0f, -0.9f, 0xff0ff0ff,}, 
    { -1.0f+(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xff0ff0ff,}, /////Triangle  
    //FRONT Inner Wall Right1
    { 0.9f,-1.0f+doorHeight, -0.9f, 0xff0ff0ff,}, 
    { 0.9f,-1.0f, -0.9f, 0xff0ff0ff,}, 
    { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xff0ff0ff,}, /////Triangle
    //FRONT Inner Wall Right2
    { 0.9f,-1.0f+doorHeight, -0.9f, 0xff0000ff,}, 
    { 1.0f-(scale-doorWidth),-1.0f, -0.9f, 0xff0000ff,}, 
    { 1.0f-(scale-doorWidth),-1.0f+doorHeight, -0.9f, 0xff0000ff,}, /////Triangle
    };
//*******************************************************************
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
//-------------------------------------------------------------------
void SetupMatrices()
{
    static float time = 0.0f;
    time += 10.0f;
    D3DXMatrixIdentity( &g_matWorld );
    D3DXMatrixRotationYawPitchRoll( &g_matWorld,
        time/1000.0f,
        time/700.0f,
        time/850.0f );
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &g_matWorld );
    D3DXMatrixLookAtLH( &g_matView, &D3DXVECTOR3( 0.0f, 0.0f,-5.0f ),
        &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
        &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &g_matView );
    D3DXMatrixPerspectiveLH(&g_matProj, 2.0f, 2.0f/1.5f,
        1.0f, 10000.0f);
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &g_matProj );
}
void TestForMouse()
{
    DIMOUSESTATE mouseState;
    m_pDIMouseDevice->GetDeviceState(sizeof(mouseState),
        (LPVOID)&mouseState);
    if(mouseState.rgbButtons[0] & 0x80) // left mouse button down
    {
    }
}
//************************ MESSAGE HANDLER **************************
LRESULT CALLBACK WindowProc(HWND hwnd, 
    UINT msg, 
    WPARAM wparam, 
    LPARAM lparam)
{
    // this is the main message handler of the system
    PAINTSTRUCT     ps; // used in WM_PAINT
    HDC             hdc;    // handle to a device context
    // what is the message 
    switch(msg)
    {   
    case WM_CREATE: 
        {
            // do initialization stuff here
            return(0);
        } 
    case WM_PAINT: 
        {
            // validate the window
            hdc = BeginPaint(hwnd,&ps);  
            EndPaint(hwnd,&ps);
            return(0);
        } 
    case WM_KEYDOWN:
        {
            // Handle any non-accelerated key commands
            switch (wparam)
            {
            case VK_ESCAPE:
            case VK_F12:
                PostMessage(hwnd, WM_CLOSE, 0, 0);
                return (0);
            default:
                char message[15];
                sprintf_s(message, "Key Pressed: %c", (char)wparam);
                MessageBox(NULL, message, "Key Pressed", MB_OK);
            }
            break;
        }
    case WM_DESTROY: 
        {
            // kill the application         
            PostQuitMessage(0);
            return(0);
        }
    default:
        break;
    } // end switch
    // process any messages that wasn't taken care of
    return (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc

//********************* END OF MESSAGE HANDLER ***********************
void InitializeDX(HWND hwnd)
{ 
    if(!( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        MessageBox(hwnd,"Direct3d Create problem", NULL, NULL);
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    if(FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &d3dpp, &g_pd3dDevice ) ) )
        MessageBox(hwnd,"CreateDevice problem", NULL, NULL);
    //InitializeCircleArray();
    //InitializeSquareArray();
    //*************************** Create Vertex Buffer ****************************
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( numberOfVertecies*sizeof(CUSTOMVERTEX),
        0 /* Usage */, D3DFVF_CUSTOMVERTEX,
        D3DPOOL_MANAGED, &g_pVB, NULL ) ) )
        MessageBox(hwnd,"Vertex Buffer problem",NULL,NULL);
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) )
        MessageBox(hwnd,"Vertex Lock Problem",NULL,NULL);
    memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );
    g_pVB->Unlock();
    g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
}
void InitializeDI(HWND hwnd)
{
    if(FAILED(DirectInput8Create(GetModuleHandle(NULL),
        DIRECTINPUT_VERSION,
        IID_IDirectInput8,
        (void**)&m_pDIObject,
        NULL)))
        MessageBox(hwnd,"DirectInput8Create() failed!",NULL,NULL);
    // Setup Mouse Input
    if(FAILED(m_pDIObject->CreateDevice(GUID_SysMouse,
        &m_pDIMouseDevice,
        NULL)))
        MessageBox(hwnd,"CreateDevice() failed!",NULL,NULL);
    if(FAILED(m_pDIMouseDevice->SetDataFormat(&c_dfDIMouse)))
        MessageBox(hwnd,"SetDataFormat() failed!",NULL,NULL);
    if(FAILED(m_pDIMouseDevice->SetCooperativeLevel(hwnd,
        DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
        MessageBox(hwnd,"SetCooperativeLevel() failed!",NULL,NULL);
    if(FAILED(m_pDIMouseDevice->Acquire()))
        MessageBox(hwnd,"Acquire() failed!",NULL,NULL);
}
//**************************Render and display the scene***********************
void Render()
{
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
    // Turn off D3D lighting,
    // providing our own vertex colours
    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
    // Turn off culling
    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
    // Begin the scene
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        SetupMatrices();
        // Rendering of scene objects can happen here
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        //g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 179 ); // 179 triangles from 181 vertices
        //g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0,  numberOfTriangles ); //1 triangle
        // End the scene
        g_pd3dDevice->EndScene();
    }
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
//************************ WIN MAIN***********************
int WINAPI WinMain( HINSTANCE hinstance,
    HINSTANCE hprevinstance,
    LPSTR lpcmdline,
    int ncmdshow)
{
    WNDCLASS    winclass;   // this will hold the class
    HWND        hwnd;       // generic window handle
    MSG         msg;        // generic message
    // first fill in the window class stucture
    winclass.style          = CS_HREDRAW | CS_VREDRAW;                  
    winclass.lpfnWndProc    = WindowProc;
    winclass.cbClsExtra     = 0;
    winclass.cbWndExtra     = 0;
    winclass.hInstance      = hinstance;
    winclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
    winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
    //  winclass.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
    //  winclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
    winclass.hbrBackground  = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0));
    winclass.lpszMenuName   = NULL;
    winclass.lpszClassName  = "DX9WinClass";
    // register the window class
    if (!RegisterClass(&winclass))
        return(0);
    // create the window
    if (!(hwnd = CreateWindow( "DX9WinClass", // class
        TITLE,       // title
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        0,
        0,
        //Set the size of the window to the size of the screen 
        600,
        400,
        //GetSystemMetrics(SM_CXSCREEN),
        //GetSystemMetrics(SM_CYSCREEN),
        NULL,      // handle to parent 
        NULL,      // handle to menu
        hinstance,  // instance
        NULL))) // creation parms
        return(0);
    InitializeDX(hwnd);
    InitializeDI(hwnd);
    // enter main event loop
    bool quit = false;
    while(!quit)
    {
        TestForMouse();
        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        { 
            // test if this is a quit
            if (msg.message == WM_QUIT) quit = true;
            // translate any accelerator keys
            TranslateMessage(&msg);
            // send the message to the window proc
            DispatchMessage(&msg);
        } // end if
        else {
            Render();
        }
    } // end while
    //Set Mouse Free Run Away Mouse
    m_pDIMouseDevice->Release();
    // return to Windows like this
    return(msg.wParam);
} // end WinMain

//************************ END OF WIN MAIN *******************

通常您使用外部程序(例如Blender 3D)创建模型,然后将模型读取到您的程序中。也许在你的情况下,最好看看现有的免费游戏引擎,以便更好地了解它是如何工作的,人们喜欢使用的免费游戏引擎是quake3引擎,尽管它有点过时,但它应该能让你更好地理解,也许可以作为你自己的引擎的灵感。另一个推荐的更简单的图形引擎是Ogre3D