⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 forcefeedback.cpp

📁 是《3D游戏编程》的代码 买了这本书
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// 名称: RenderSene.cpp
// 
// 功能: 进行3D场景的渲染——使用显示内存的顶点缓冲区。
//       
//-----------------------------------------------------------------------------

#include <tchar.h>
#include <windows.h>
#include <basetsd.h>

// 包含Direct3D头文件
#include <d3d8.h>
#include <d3dx8.h>
#include <dinput.h>
#include <mmsystem.h>

// Windows类的名称宏定义
#define  MY_WINCLASS_NAME      "Direct3D"

struct PLAYER
{
    D3DXVECTOR3    LookAt[3];
};

// 定义个表示顶点的结构
struct CUSTOMVERTEX
{
    FLOAT x, y, z; // x,y,z表示点的三维坐标值,
    DWORD color;        // 顶点颜色
};

// 自定义的顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

// 定义全局变量
LPDIRECT3D8             g_pMyD3D          = NULL; // 定义Direct3D对象的指针
LPDIRECT3DDEVICE8       g_pMyd3dDevice    = NULL; // 定义Direct3D设备指针
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferRec     = NULL; // 定义顶点缓冲区对象指针
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferLine     = NULL;

PLAYER  g_Player;
float   g_Angle = 0;

#define LINE_VECTOR_NUM 20

// 定义包含4个顶点的顶点数组
CUSTOMVERTEX g_Vertices[] =
{
        { -1.5f, 0.0f, 0.0f, 0xffff0000, },  
        { -1.5f, 2.0f, 0.0f, 0xffff0000, },
		{  1.5f, 0.0f, 0.0f, 0xffff0000, },
		{  1.5f, 2.0f, 0.0f, 0xffff0000, },  

};
#define GRID_WIDTH       20.0f
#define NUM_GRID         20


#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#define SAMPLE_BUFFER_SIZE 8
#define TIME2FRAME 15

LPDIRECTINPUT8       g_pDirectInput       = NULL;         
LPDIRECTINPUTDEVICE8 g_pJoystick = NULL;     
LPDIRECTINPUTEFFECT  g_pEffect   = NULL;

//-----------------------------------------------------------------------------
// 名称: JoystickFree()
// 功能: 释放游戏杆设备设备。
// 输入: 
// 返回: 
//-----------------------------------------------------------------------------
VOID JoystickFree()
{
    // 释放设备
    if( g_pJoystick ) 
        g_pJoystick->Unacquire();
    
    // 释放所有的DirectInput资源
    SAFE_RELEASE(g_pEffect);
    SAFE_RELEASE( g_pJoystick );
    SAFE_RELEASE( g_pDirectInput );
}

//-----------------------------------------------------------------------------
// 名称: EffectStart()
// 功能: 打开力反馈效果的函数。
// 输入: 力反馈效果接口指针
// 返回: 函数返回S_OK表示力反馈打开操作成功,否则失败
//        
//-----------------------------------------------------------------------------
HRESULT EffectStart( LPDIRECTINPUTEFFECT  pEffect )
{
    HRESULT              hr;

	if(pEffect)
		hr = pEffect->Start(1, 0);

	return hr;
}
 

//-----------------------------------------------------------------------------
// 名称: EffectEnumCallback()
// 功能: 枚举游戏杆力反馈效果时的回调函数。
// 输入: 设备对象句柄和传入的指定参数
// 返回: 函数返回DIENUM_STOP表示停止枚举操作,
//        返回DIENUM_CONTINUE表示需要继续枚举游戏杆设备。
//-----------------------------------------------------------------------------
BOOL CALLBACK EffectEnumCallback( LPCDIEFFECTINFO* pdei,
                                VOID* pContext )
{
    HRESULT              hr;
    LPDIRECTINPUTDEVICE8 lpdid = (LPDIRECTINPUTDEVICE8)pContext;   
 
    if (DIEFT_GETTYPE(pdei) == DIEFT_CONSTANTFORCE)
    {
 
        // 创建力反馈效果 
		DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
		LONG            rglDirection[2] = { 0, 0 };
		DICONSTANTFORCE cf              = { 0 };
		
		DIEFFECT eff;
		ZeroMemory( &eff, sizeof(eff) );
		eff.dwSize                  = sizeof(DIEFFECT);
		eff.dwFlags                 = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
		eff.dwDuration              = INFINITE;
		eff.dwSamplePeriod          = 0;
		eff.dwGain                  = DI_FFNOMINALMAX;
		eff.dwTriggerButton         = DIEB_NOTRIGGER;
		eff.dwTriggerRepeatInterval = 0;
		eff.cAxes                   = 2;
		eff.rgdwAxes                = rgdwAxes;
		eff.rglDirection            = rglDirection;
		eff.lpEnvelope              = 0;
		eff.cbTypeSpecificParams    = sizeof(DICONSTANTFORCE);
		eff.lpvTypeSpecificParams   = &cf;
		eff.dwStartDelay            = 0;

		if( FAILED( hr = lpdid->CreateEffect( GUID_ConstantForce, 
                                              &eff, &g_pEffect, NULL ) ) )
		{
			return DIENUM_CONTINUE;
		}

		return DIENUM_STOP;
    }

    return DIENUM_CONTINUE;
}



//-----------------------------------------------------------------------------
// 名称: JoystickAxesEnumCallback()
// 功能: 枚举游戏杆坐标系统时的回调函数。
// 输入: 设备对象句柄和传入的指定参数
// 返回: 函数返回DIENUM_STOP表示停止枚举操作,
//        返回DIENUM_CONTINUE表示需要继续枚举游戏杆设备。
//-----------------------------------------------------------------------------
BOOL CALLBACK JoystickAxesEnumCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
                                VOID* pContext )
{
    HWND hDlg = (HWND)pContext;

    DIPROPRANGE diprg; 
    diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
    diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
    diprg.diph.dwHow        = DIPH_BYID; 
    diprg.diph.dwObj        = pdidoi->dwType; // Specify the enumerated axis
    diprg.lMin              = -1000; 
    diprg.lMax              = +1000; 
    
	// 设置坐标的取值范围
	if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
		return DIENUM_STOP;

    return DIENUM_CONTINUE;
}


//-----------------------------------------------------------------------------
// 名称: JoysticksEnumCallback()
// 功能: 创建游戏杆设备时的回调函数。
// 输入: 设备句柄和传入的指定参数
// 返回: 函数返回DIENUM_STOP表示停止枚举操作,
//        返回DIENUM_CONTINUE表示需要继续枚举游戏杆设备。
//-----------------------------------------------------------------------------
BOOL CALLBACK JoysticksEnumCallback( const DIDEVICEINSTANCE* pdidInstance,
                                     VOID* pContext )
{
    HRESULT hr;

    // 根据得到的枚举设备创建DirectInput设备
    hr = g_pDirectInput->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL );

    // 创建失败,需要继续枚举
    if( FAILED(hr) ) 
        return DIENUM_CONTINUE;

    // 使用系统中的第一个可用的游戏杆设备,停止枚举操作
    return DIENUM_STOP;
}


//-----------------------------------------------------------------------------
// 名称: JoystickCreate()
// 功能: 创建游戏杆设备
// 输入: 窗口句柄
// 返回: 成功返回S_OK,
//       失败返回错误代码
//-----------------------------------------------------------------------------
HRESULT JoystickCreate( HWND hWnd )
{
    HRESULT hr;      

    // 创建DirectInput对象
    if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
                                         IID_IDirectInput8, (VOID**)&g_pDirectInput, NULL ) ) )
        return hr;
    
    // 枚举游戏杆设备,并且在回调函数中创建DirectInput设备对象
    if( FAILED( hr = g_pDirectInput->EnumDevices( DI8DEVCLASS_GAMECTRL, 
                                         JoysticksEnumCallback,
                                         NULL, DIEDFL_ATTACHEDONLY ) ) )
        return hr;
    
	// 如果没有创建成功游戏杆设备,显示提示对话框
	if(g_pJoystick == NULL)
	{
		MessageBox( NULL, "游戏杆没有找到", 
                    "使用游戏杆设备例子程序", 
                    MB_ICONERROR | MB_OK );
		return E_FAIL;
	}

    // 设置键盘数据为通用鼠标数据格式
    if( FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick ) ) )
        return hr;
   
	// 设置鼠标的协作水平为独占方式和前台操作方式
	hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );

    if( hr == DIERR_UNSUPPORTED )
    {
        JoystickFree();
        MessageBox( hWnd, _T("SetCooperativeLevel() 不支持的协作模式\n"), 
						  _T("Effect"), MB_OK );
        return E_FAIL;
    }

    if( FAILED(hr) )
        return hr;

    // 枚举设备的坐标系统对象,并在回调函数中进行坐标范围的设置
    if ( FAILED( hr = g_pJoystick->EnumObjects( JoystickAxesEnumCallback, 
                                                (VOID*)hWnd, DIDFT_AXIS ) ) )
        return hr;

	// 获取创建的键盘设备,在读取设备输入数据之前,这是必须的操作步骤
    g_pJoystick->Acquire();

	// 枚举力反馈效果,并在回调函数中创建持续力效果
	if(FAILED(hr = g_pJoystick->EnumEffects((LPDIENUMEFFECTSCALLBACK) EffectEnumCallback,
                          &g_pJoystick, 
                          DIEFT_ALL)))
        return hr;
 
	if(g_pEffect == NULL)
	{
        JoystickFree();
        MessageBox( hWnd, _T("创建力反馈效果失败\n"), 
						  _T("Effect"), MB_OK );
        return E_FAIL;
	}

    return S_OK;
}


//-----------------------------------------------------------------------------
// 名称: JoystickRead()
// 功能: 读取鼠标设备的输入数据。
// 输入: 
// 返回: 成功返回S_OK,失败返回错误代码
//-----------------------------------------------------------------------------
HRESULT JoystickRead()
{
	// 定义游戏杆数据格式
    DIJOYSTATE joystick;            
	HRESULT  hr; 
 
    ZeroMemory( &joystick, sizeof(DIJOYSTATE) );

	// 在读取游戏杆设备的输入数据之前,必须轮询游戏杆设备
    hr = g_pJoystick->Poll(); 

	if FAILED(hr) 
	{ 
        hr = g_pJoystick->Acquire();
        while( hr == DIERR_INPUTLOST ) 
            hr = g_pJoystick->Acquire();

        return S_OK; 
	} 

	// 读取游戏杆的输入状态
    if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &joystick ) ) )
        return hr; 

	// 判断输入的方向
	// 游戏杆向右方向移动的处理 
	if (joystick.lX > 0)
	{
		g_Angle+=0.01f;
        g_Player.LookAt[1].x = g_Player.LookAt[0].x+sinf(g_Angle);
        g_Player.LookAt[1].z = g_Player.LookAt[0].z+cosf(g_Angle);

	}
	// 游戏杆向左方向移动的处理 
	else if(joystick.lX < 0)
	{
		g_Angle-=0.01f;
        g_Player.LookAt[1].x = g_Player.LookAt[0].x+sinf(g_Angle);
        g_Player.LookAt[1].z = g_Player.LookAt[0].z+cosf(g_Angle);

	}
 
	// 游戏杆向后移动的处理  
	if (joystick.lY < 0) 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -