このブログを検索

2019年5月12日日曜日

【C++】 DirectX11 - XInputゲームパッド入力

【C++】 DirectX11 - XInputゲームパッド入力
(2019年5月12日)


■使用ソフト
・Visual Studio Community 2019


■言語
・C/C++


■Windows SDK バージョン
・10.0.17763.0
 ※Windows SDK バージョンの変更方法


■手順
1.基本的には以下の流れ参照
【C++】 DirectX11 - GetAsyncKeyStateキーボード入力 //これをベースにコードを変更する
【C++】 メッセージボックスの作成 //プロジェクトの作成からビルドまでの操作方法について

2.以下の4つのファイルを作成してビルドを行う。
(1)Main.h
(2)Main.cpp
(3)DirectX.h
(4)DirectX.cpp

(1)Main.h
#pragma once

#include <windows.h>
#pragma comment(lib,"winmm.lib")

//--------------------------------------------------------------------------------------
// Windowクラス:Window関係
//--------------------------------------------------------------------------------------
class Window
{
public:
    HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow);
    void InitFps();
    void CalculationFps();
    void CalculationSleep();
    void CalculationFrameTime();

    static HWND GethWnd();
    static int GetClientWidth();
    static int GetClientHeight();
    static double GetFps();
    static double GetFrameTime();
private:
    LARGE_INTEGER m_freq = { 0 };
    LARGE_INTEGER m_starttime = { 0 };
    LARGE_INTEGER m_nowtime = { 0 };
    LARGE_INTEGER m_frametime_a = { 0 };
    LARGE_INTEGER m_frametime_b = { 0 };
    int m_iCount = 0;

    static HWND g_hWnd;
    static int g_iClientWidth;
    static int g_iClientHeight;
    static double g_dFps;
    static double g_dFrameTime;
};

(2)Main.cpp
#include "Main.h"
#include "DirectX.h"

//--------------------------------------------------------------------------------------
// 静的メンバ
//--------------------------------------------------------------------------------------
HWND Window::g_hWnd = nullptr;//ウィンドウハンドル
int Window::g_iClientWidth = 800;//クライアント領域の横幅
int Window::g_iClientHeight = 600;//クライアント領域の高さ
double Window::g_dFps = 0;//FPS
double Window::g_dFrameTime = 0;//1フレームあたりの時間

//--------------------------------------------------------------------------------------
// 前方宣言
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

//--------------------------------------------------------------------------------------
// wWinMain()関数:エントリーポイント
//--------------------------------------------------------------------------------------
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
    if (FAILED(CoInitialize(nullptr)))//COMの初期化
        return 0;

    Window win;

    if (FAILED(win.InitWindow(hInstance, nCmdShow)))
        return 0;

    DirectX11 dx;

    if (FAILED(dx.InitDevice()))
        return 0;

    win.InitFps();

    // メインメッセージループ
    MSG msg = { 0 };
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            win.CalculationFps();

            win.CalculationFrameTime();

            dx.Render();

            win.CalculationSleep();
        }
    }

    CoUninitialize();//COMの終了処理

    return (int)msg.wParam;
}

//--------------------------------------------------------------------------------------
// WndProc()関数:ウィンドウプロシージャ
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch (uiMessage)
    {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hWnd, uiMessage, wParam, lParam);
    }

    return 0;
}

//--------------------------------------------------------------------------------------
// Window::InitWindow()関数:ウィンドウの表示
//--------------------------------------------------------------------------------------
HRESULT Window::InitWindow(HINSTANCE hInstance, int nCmdShow)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = nullptr;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = nullptr;
    wcex.lpszClassName = L"WindowClass";
    wcex.hIconSm = nullptr;
    if (!RegisterClassEx(&wcex))
        return E_FAIL;

    RECT rc = { 0, 0, g_iClientWidth, g_iClientHeight };
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
    g_hWnd = CreateWindow(L"WindowClass", L"XInputゲームパッド入力",//★---変更---
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance,
        nullptr);
    if (!g_hWnd)
        return E_FAIL;

    ShowWindow(g_hWnd, nCmdShow);

    return S_OK;
}

//--------------------------------------------------------------------------------------
// Window::InitFps()関数:FPS計測の初期化
//--------------------------------------------------------------------------------------
void Window::InitFps()
{
    QueryPerformanceFrequency(&m_freq);
    QueryPerformanceCounter(&m_starttime);//現在の時間を取得(1フレーム目)
}

//--------------------------------------------------------------------------------------
// Window::CalculationFps()関数:FPS計測
//--------------------------------------------------------------------------------------
void Window::CalculationFps()
{
    if (m_iCount == 60)//カウントが60の時の処理
    {
        QueryPerformanceCounter(&m_nowtime);//現在の時間を取得(60フレーム目)
        //FPS = 1秒 / 1フレームの描画にかかる時間
        //    = 1000ms / ((現在の時間ms - 1フレーム目の時間ms) / 60フレーム)
        g_dFps = 1000.0 / (static_cast<double>((m_nowtime.QuadPart - m_starttime.QuadPart) * 1000 / m_freq.QuadPart) / 60.0);
        m_iCount = 0;//カウントを初期値に戻す
        m_starttime = m_nowtime;//1フレーム目の時間を現在の時間にする
    }
    m_iCount++;//カウント+1
}

//--------------------------------------------------------------------------------------
// Window::CalculationSleep()関数:Sleepさせる時間の計算
//--------------------------------------------------------------------------------------
void Window::CalculationSleep()
{
    QueryPerformanceCounter(&m_nowtime);//現在の時間を取得
    //Sleepさせる時間ms = 1フレーム目から現在のフレームまでの描画にかかるべき時間ms - 1フレーム目から現在のフレームまで実際にかかった時間ms
    //                  = (1000ms / 60)*フレーム数 - (現在の時間ms - 1フレーム目の時間ms)
    DWORD dwSleepTime = static_cast<DWORD>((1000.0 / 60.0) * m_iCount - (m_nowtime.QuadPart - m_starttime.QuadPart) * 1000 / m_freq.QuadPart);
    if (dwSleepTime > 0 && dwSleepTime < 18)//大きく変動がなければSleepTimeは1~17の間に納まる
    {
        timeBeginPeriod(1);
        Sleep(dwSleepTime);
        timeEndPeriod(1);
    }
    else//大きく変動があった場合
    {
        timeBeginPeriod(1);
        Sleep(1);
        timeEndPeriod(1);
    }
}

//--------------------------------------------------------------------------------------
// Window::CalculationFrameTime()関数:1フレームあたりの時間の計測
//--------------------------------------------------------------------------------------
void Window::CalculationFrameTime()
{
    static int iFlg;
    if (iFlg == 0)
    {
        QueryPerformanceCounter(&m_frametime_a);
        iFlg = 1;
    }
    QueryPerformanceCounter(&m_frametime_b);
    g_dFrameTime = (m_frametime_b.QuadPart - m_frametime_a.QuadPart) * 1000.0 / m_freq.QuadPart;
    m_frametime_a = m_frametime_b;
}

//--------------------------------------------------------------------------------------
// Window::GethWnd()関数:hWndの取得
//--------------------------------------------------------------------------------------
HWND Window::GethWnd()
{
    return g_hWnd;
}

//--------------------------------------------------------------------------------------
// Window::GetClientWidth()関数:クライアント領域の横幅の取得
//--------------------------------------------------------------------------------------
int Window::GetClientWidth()
{
    return g_iClientWidth;
}

//--------------------------------------------------------------------------------------
// Window::GetClientHeight()関数:クライアント領域の高さの取得
//--------------------------------------------------------------------------------------
int Window::GetClientHeight()
{
    return g_iClientHeight;
}

//--------------------------------------------------------------------------------------
// Window::GetFps()関数:FPSの取得
//--------------------------------------------------------------------------------------
double Window::GetFps()
{
    return g_dFps;
}

//--------------------------------------------------------------------------------------
// Window::GetFrameTime()関数:1フレームあたりの時間の取得
//--------------------------------------------------------------------------------------
double Window::GetFrameTime()
{
    return g_dFrameTime;
}

(3)DirectX.h
#pragma once

#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d2d1.lib")
#pragma comment(lib,"dwrite.lib")
#pragma comment (lib, "xinput.lib")//---★追加---
#include <d3d11_1.h>
#include <directxcolors.h>
#include <d2d1_1.h>
#include <dwrite.h>
#include <wchar.h>
#include <wrl/client.h>
#include <random>
#include <xinput.h>//---★追加---

//--------------------------------------------------------------------------------------
// DirectX11クラス:DirectX関係
//--------------------------------------------------------------------------------------
class DirectX11
{
public:
    DirectX11();
    ~DirectX11();
    HRESULT InitDevice();
    void Render();
private:
    //------------------------------------------------------------
    // DirectX11とDirect2D 1.1の初期化
    //------------------------------------------------------------
    Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_D3DDeviceContext;
    Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_D2DDeviceContext;
    Microsoft::WRL::ComPtr<IDXGISwapChain1> m_DXGISwapChain1;
    Microsoft::WRL::ComPtr<ID2D1Bitmap1> m_D2DBitmap1;
    Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_D3DRenderTargetView;

    //------------------------------------------------------------
    // DirectWriteの初期化
    //------------------------------------------------------------
    Microsoft::WRL::ComPtr<IDWriteTextFormat> m_DWriteTextFormat;
    Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_D2DSolidBrush;
};

(4)DirectX.cpp
#include "Main.h"
#include "DirectX.h"

//--------------------------------------------------------------------------------------
// DirectX11::DirectX11()関数:コンストラクタ
//--------------------------------------------------------------------------------------
DirectX11::DirectX11()
{

}

//--------------------------------------------------------------------------------------
// DirectX11::~DirectX11関数:デストラクタ
//--------------------------------------------------------------------------------------
DirectX11::~DirectX11()
{

}

//--------------------------------------------------------------------------------------
// DirectX11::InitDevice():DirectX関係の初期化
//--------------------------------------------------------------------------------------
HRESULT DirectX11::InitDevice()
{
    //------------------------------------------------------------
    // DirectX11とDirect2D 1.1の初期化
    //------------------------------------------------------------
    HRESULT hr = S_OK;

    UINT uiDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;//DirectX11上でDirect2Dを使用するために必要
#ifdef _DEBUG
    uiDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_DRIVER_TYPE drivertypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT uiDriverTypesNum = ARRAYSIZE(drivertypes);

    D3D_FEATURE_LEVEL featurelevels[] =
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
    };
    UINT uiFeatureLevelsNum = ARRAYSIZE(featurelevels);

    Microsoft::WRL::ComPtr<ID3D11Device> D3DDevice;
    D3D_DRIVER_TYPE drivertype = D3D_DRIVER_TYPE_NULL;
    D3D_FEATURE_LEVEL featurelevel = D3D_FEATURE_LEVEL_11_0;
    for (UINT uiDriverTypeIndex = 0; uiDriverTypeIndex < uiDriverTypesNum; uiDriverTypeIndex++)
    {
        drivertype = drivertypes[uiDriverTypeIndex];
        hr = D3D11CreateDevice(nullptr, drivertype, nullptr, uiDeviceFlags, featurelevels, uiFeatureLevelsNum,
            D3D11_SDK_VERSION, &D3DDevice, &featurelevel, &m_D3DDeviceContext);//&D3DDevice &m_D3DDeviceContext 初期化

        if (hr == E_INVALIDARG)
        {
            hr = D3D11CreateDevice(nullptr, drivertype, nullptr, uiDeviceFlags, &featurelevels[1], uiFeatureLevelsNum - 1,
                D3D11_SDK_VERSION, &D3DDevice, &featurelevel, &m_D3DDeviceContext);//&D3DDevice &m_D3DDeviceContext 初期化
        }

        if (SUCCEEDED(hr))
            break;
    }
    if (FAILED(hr))
        return hr;

    Microsoft::WRL::ComPtr<IDXGIDevice2> DXGIDevice2;
    hr = D3DDevice.As(&DXGIDevice2);//D3DDevice->QueryInterface()ではなくD3DDevice.As()、&DXGIDevice2 初期化
    if (FAILED(hr))
        return hr;

    Microsoft::WRL::ComPtr<ID2D1Factory1> D2DFactory1;
    D2D1_FACTORY_OPTIONS factoryoptions = {};
#ifdef _DEBUG
    factoryoptions.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif
    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, factoryoptions, D2DFactory1.GetAddressOf());//&D2DFactory1ではなくD2DFactory1.GetAddressOf()
    if (FAILED(hr))
        return hr;

    Microsoft::WRL::ComPtr<ID2D1Device> D2D1Device;
    hr = D2DFactory1->CreateDevice(DXGIDevice2.Get(), &D2D1Device);//DXGIDevice2ではなくDXGIDevice2.Get()、&D2D1Device 初期化
    if (FAILED(hr))
        return hr;

    hr = D2D1Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &m_D2DDeviceContext);//&m_D2DDeviceContext 初期化
    if (FAILED(hr))
        return hr;

    Microsoft::WRL::ComPtr<IDXGIAdapter> DXGIAdapter;
    hr = DXGIDevice2->GetAdapter(&DXGIAdapter);//&DXGIAdapter 初期化
    if (FAILED(hr))
        return hr;

    Microsoft::WRL::ComPtr<IDXGIFactory2> DXGIFactory2;
    hr = DXGIAdapter->GetParent(IID_PPV_ARGS(&DXGIFactory2));//&DXGIFactory2 初期化
    if (FAILED(hr))
        return hr;

    DXGI_SWAP_CHAIN_DESC1 desc = {};
    desc.Width = Window::GetClientWidth();
    desc.Height = Window::GetClientHeight();
    desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    desc.Stereo = FALSE;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    desc.BufferCount = 2;
    desc.Scaling = DXGI_SCALING_STRETCH;
    desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;

    hr = DXGIFactory2->CreateSwapChainForHwnd(D3DDevice.Get(), Window::GethWnd(), &desc, nullptr, nullptr, &m_DXGISwapChain1);//D3DDeviceではなくD3DDevice.Get()、&m_DXGISwapChain1 初期化
    if (FAILED(hr))
        return hr;

    (void)DXGIDevice2->SetMaximumFrameLatency(1);

    DXGIFactory2->MakeWindowAssociation(Window::GethWnd(), DXGI_MWA_NO_ALT_ENTER);//Alt+Enter時フルスクリーンを無効

    Microsoft::WRL::ComPtr<IDXGISurface2> DXGISurface2;
    hr = m_DXGISwapChain1->GetBuffer(0, IID_PPV_ARGS(&DXGISurface2));//&DXGISurface2 初期化
    if (FAILED(hr))
        return hr;

    hr = m_D2DDeviceContext->CreateBitmapFromDxgiSurface(DXGISurface2.Get(),//DXGISurface2ではなくDXGISurface2.Get()
        D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
            D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE)), &m_D2DBitmap1);//&m_D2DBitmap1 初期化
    if (FAILED(hr))
        return hr;

    m_D2DDeviceContext->SetTarget(m_D2DBitmap1.Get());//D2DBitmap1ではなくD2DBitmap1.Get()

    Microsoft::WRL::ComPtr<ID3D11Texture2D> D3DTexture2D;
    hr = m_DXGISwapChain1->GetBuffer(0, IID_PPV_ARGS(&D3DTexture2D));//&D3DTexture2D 初期化
    if (FAILED(hr))
        return hr;

    hr = D3DDevice->CreateRenderTargetView(D3DTexture2D.Get(), nullptr, &m_D3DRenderTargetView);//D3DTexture2DではなくD3DTexture2D.Get()、&m_D3DRenderTargetView 初期化
    if (FAILED(hr))
        return hr;

    m_D3DDeviceContext->OMSetRenderTargets(1, m_D3DRenderTargetView.GetAddressOf(), nullptr);//&m_D3DRenderTargetViewではなくm_D3DRenderTargetView.GetAddressOf()

    D3D11_VIEWPORT vp;
    vp.Width = (FLOAT)Window::GetClientWidth();
    vp.Height = (FLOAT)Window::GetClientHeight();
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    m_D3DDeviceContext->RSSetViewports(1, &vp);

    //------------------------------------------------------------
    // DirectWriteの初期化
    //------------------------------------------------------------
    Microsoft::WRL::ComPtr<IDWriteFactory> DWriteFactory;
    hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &DWriteFactory);//&DWriteFactory 初期化
    if (FAILED(hr))
        return hr;

    //関数CreateTextFormat()
    //第1引数:フォント名(L"メイリオ", L"Arial", L"Meiryo UI"等)
    //第2引数:フォントコレクション(nullptr)
    //第3引数:フォントの太さ(DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_WEIGHT_BOLD等)
    //第4引数:フォントスタイル(DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STYLE_OBLIQUE, DWRITE_FONT_STYLE_ITALIC)
    //第5引数:フォントの幅(DWRITE_FONT_STRETCH_NORMAL,DWRITE_FONT_STRETCH_EXTRA_EXPANDED等)
    //第6引数:フォントサイズ(20, 30等)
    //第7引数:ロケール名(L"")
    //第8引数:テキストフォーマット(&g_pTextFormat)
    hr = DWriteFactory->CreateTextFormat(L"メイリオ", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 20, L"", &m_DWriteTextFormat);//&m_DWriteTextFormat 初期化
    if (FAILED(hr))
        return hr;

    //関数SetTextAlignment()
    //第1引数:テキストの配置(DWRITE_TEXT_ALIGNMENT_LEADING:前, DWRITE_TEXT_ALIGNMENT_TRAILING:後, DWRITE_TEXT_ALIGNMENT_CENTER:中央)
    hr = m_DWriteTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
    if (FAILED(hr))
        return hr;

    //関数CreateSolidColorBrush()
    //第1引数:フォント色(D2D1::ColorF(D2D1::ColorF::Black):黒, D2D1::ColorF(D2D1::ColorF(0.0f, 0.2f, 0.9f, 1.0f)):RGBA指定)
    hr = m_D2DDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_D2DSolidBrush);//&m_D2DSolidBrush 初期化
    if (FAILED(hr))
        return hr;

    return S_OK;
}

//--------------------------------------------------------------------------------------
// DirectX11::Render():DirectX関係の描画
//--------------------------------------------------------------------------------------
void DirectX11::Render()
{
    m_D3DDeviceContext->ClearRenderTargetView(m_D3DRenderTargetView.Get(), DirectX::Colors::Aquamarine);//m_D3DRenderTargetViewではなくm_D3DRenderTargetView.Get()

    //--------------------------★変更↓--------------------------

    //------------------------------------------------------------
    // 初期設定
    //------------------------------------------------------------
    static FLOAT fPosX1 = 200, fPosY1 = 300;//円の位置
    static FLOAT fRadius1 = 50;//円の半径
    static double dSpeed = 1.0;//動くスピード

    //------------------------------------------------------------
    // キー入力関係
    //------------------------------------------------------------
    //キー入力
    int iKeyA = 0, iKeyD = 0, iKeyW = 0, iKeyS = 0;
    if (GetAsyncKeyState('A') & 0x8000) iKeyA = 1;
    if (GetAsyncKeyState('D') & 0x8000) iKeyD = 1;
    if (GetAsyncKeyState('W') & 0x8000) iKeyW = 1;
    if (GetAsyncKeyState('S') & 0x8000) iKeyS = 1;
    //ゲームパッドの状態を取得
    XINPUT_STATE state;
    XInputGetState(0, &state);
    int iPad_left = 0, iPad_right = 0, iPad_up = 0, iPad_down = 0;
    int iPad_leftshoulder = 0, iPad_rightshoulder = 0;
    int iPad_A = 0, iPad_B = 0, iPad_X = 0, iPad_Y = 0;
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) iPad_left = 1;//ゲームパッド十字キー左
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) iPad_right = 1;//ゲームパッド十字キー右
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) iPad_up = 1;//ゲームパッド十字キー上
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) iPad_down = 1;//ゲームパッド十字キー下
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) iPad_leftshoulder = 1;//ゲームパッドL
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) iPad_rightshoulder = 1;//ゲームパッドR
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A) iPad_A = 1;//ゲームパッドA
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B) iPad_B = 1;//ゲームパッドB
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X) iPad_X = 1;//ゲームパッドX
    if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) iPad_Y = 1;//ゲームパッドY
    //ゲームパッドアナログスティックのデッドゾーン処理
    if ((state.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && state.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) &&
        (state.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && state.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE))
    {
        state.Gamepad.sThumbLX = 0;
        state.Gamepad.sThumbLY = 0;
    }

    //キー入力時の処理
    double dValue = 1;
    if (iKeyA || iKeyD || iPad_left || iPad_right)
    {
        if (iKeyW || iKeyS || iPad_up || iPad_down)
        {
            dValue = 1 / sqrt(2);//斜め入力時は1/√2倍する
        }
        else
        {
            dValue = 1;
        }
    }
    else if (iKeyW || iKeyS || iPad_up || iPad_down)
    {
        dValue = 1;
    }

    if (state.Gamepad.sThumbLX != 0 || state.Gamepad.sThumbLY != 0)//ゲームパッドアナログスティック入力時処理
    {
        fPosX1 += static_cast<FLOAT>(state.Gamepad.sThumbLX / 32767.0 * Window::GetFrameTime() * dSpeed);
        if (fPosX1 < fRadius1)
        {
            fPosX1 = fRadius1;
        }
        if (fPosX1 > Window::GetClientWidth() - fRadius1)
        {
            fPosX1 = Window::GetClientWidth() - fRadius1;
        }
        fPosY1 -= static_cast<FLOAT>(state.Gamepad.sThumbLY / 32767.0 * Window::GetFrameTime() * dSpeed);
        if (fPosY1 < fRadius1)
        {
            fPosY1 = fRadius1;
        }
        if (fPosY1 > Window::GetClientHeight() - fRadius1)
        {
            fPosY1 = Window::GetClientHeight() - fRadius1;
        }
    }
    else//キーボード入力時処理
    {
        if (iKeyA || iPad_left)
        {
            fPosX1 -= static_cast<FLOAT>(Window::GetFrameTime() * dSpeed * dValue);
            if (fPosX1 < fRadius1)
            {
                fPosX1 = fRadius1;
            }
        }
        if (iKeyD || iPad_right)
        {
            fPosX1 += static_cast<FLOAT>(Window::GetFrameTime() * dSpeed * dValue);
            if (fPosX1 > Window::GetClientWidth() - fRadius1)
            {
                fPosX1 = Window::GetClientWidth() - fRadius1;
            }
        }
        if (iKeyW || iPad_up)
        {
            fPosY1 -= static_cast<FLOAT>(Window::GetFrameTime() * dSpeed * dValue);
            if (fPosY1 < fRadius1)
            {
                fPosY1 = fRadius1;
            }
        }
        if (iKeyS || iPad_down)
        {
            fPosY1 += static_cast<FLOAT>(Window::GetFrameTime() * dSpeed * dValue);
            if (fPosY1 > Window::GetClientHeight() - fRadius1)
            {
                fPosY1 = Window::GetClientHeight() - fRadius1;
            }
        }
    }

    //ゲームパッドのAまたはBを押した時の処理:ゲームパッドの振動
    XINPUT_VIBRATION vibration;
    vibration.wLeftMotorSpeed = 0;
    vibration.wRightMotorSpeed = 0;
    XInputSetState(0, &vibration);
    if (iPad_A)
    {
        vibration.wLeftMotorSpeed = 65535;
        XInputSetState(0, &vibration);
    }
    if (iPad_B)
    {
        vibration.wRightMotorSpeed = 65535;
        XInputSetState(0, &vibration);
    }

    //------------------------------------------------------------
    // 文字操作
    //------------------------------------------------------------
    //FPS表示用
    WCHAR wcText1[256] = { 0 };
    swprintf(wcText1, 256, L"FPS=%lf", Window::GetFps());
    //キー入力状態表示用
    WCHAR wcText2[256] = { 0 };
    swprintf(wcText2, 256, L"A=%d D=%d W=%d S=%d", iKeyA, iKeyD, iKeyW, iKeyS);
    //ゲームパッド入力状態表示用
    WCHAR wcText3[256] = { 0 };
    swprintf(wcText3, 256, L"PAD_LEFT=%d PAD_RIGHT=%d PAD_UP=%d PAD_DOWN=%d", iPad_left, iPad_right, iPad_up, iPad_down);
    WCHAR wcText4[256] = { 0 };
    swprintf(wcText4, 256, L"LEFT_SHOULDER=%d RIGHT_SHOULDER=%d", iPad_leftshoulder, iPad_rightshoulder);
    WCHAR wcText5[256] = { 0 };
    swprintf(wcText5, 256, L"PAD_A=%d PAD_B=%d PAD_X=%d PAD_Y=%d", iPad_A, iPad_B, iPad_X, iPad_Y);
    WCHAR wcText6[256] = { 0 };
    swprintf(wcText6, 256, L"sThumbLX=%d sThumbLY=%d", state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);
    WCHAR wcText7[256] = { 0 };
    swprintf(wcText7, 256, L"bLeftTrigger=%d bRightTrigger=%d", state.Gamepad.bLeftTrigger, state.Gamepad.bRightTrigger);

    //------------------------------------------------------------
    // 2D描画
    //------------------------------------------------------------
    m_D2DDeviceContext->BeginDraw();
    //関数DrawEllipse() 円の描画
    //第1引数:D2D1::Ellipse(D2D1::Point2F(円の中心X, 円の中心Y), 半径X, 半径Y)
    //第2引数:ブラシ
    //第3引数:線の太さ
    m_D2DDeviceContext->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(fPosX1, fPosY1), fRadius1, fRadius1), m_D2DSolidBrush.Get(), 1);//円の描画
    m_D2DDeviceContext->DrawText(wcText1, ARRAYSIZE(wcText1) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 0, 800, 20), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);//m_DWriteTextFormatではなくm_DWriteTextFormat.Get()
    m_D2DDeviceContext->DrawText(wcText2, ARRAYSIZE(wcText2) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 20, 800, 40), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    m_D2DDeviceContext->DrawText(wcText3, ARRAYSIZE(wcText3) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 40, 800, 60), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    m_D2DDeviceContext->DrawText(wcText4, ARRAYSIZE(wcText4) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 60, 800, 80), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    m_D2DDeviceContext->DrawText(wcText5, ARRAYSIZE(wcText5) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 80, 800, 100), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    m_D2DDeviceContext->DrawText(wcText6, ARRAYSIZE(wcText6) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 100, 800, 120), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    m_D2DDeviceContext->DrawText(wcText7, ARRAYSIZE(wcText7) - 1, m_DWriteTextFormat.Get(), D2D1::RectF(0, 120, 800, 140), m_D2DSolidBrush.Get(), D2D1_DRAW_TEXT_OPTIONS_NONE);
    m_D2DDeviceContext->EndDraw();

    //--------------------------★変更↑--------------------------

    m_DXGISwapChain1->Present(0, 0);
}

★部分を追加または変更

3.Aキー:左移動、Dキー:右移動、Wキー:上移動、Sキー:下移動
  ゲームパッド十字キー:上下左右移動
  左アナログスティック:上下左右移動
  ゲームパッドA:振動1
  ゲームパッドB:振動2

0 件のコメント:

コメントを投稿