21xrx.com
2024-12-22 19:27:37 Sunday
登录
文章检索 我的文章 写文章
C++ ImGui实现血条界面
2023-07-10 13:31:54 深夜i     --     --
C++ ImGui 血条 界面 实现

在游戏开发中,血条界面是一个非常重要的元素,能够直观地显示角色的生命值,帮助玩家更好地掌握游戏场景。本文将介绍如何使用C++和ImGui实现一款简单的血条界面。

步骤一:新建工程

首先,我们需要在Visual Studio中新建一个空项目。在该项目中创建一个源文件,我们将在这个文件中编写我们的代码。为了使用ImGui,我们还需要在项目中引入ImGui的头文件和源文件。可以在ImGui的官网上下载ImGui的源码,然后将其中的imgui.cpp和imgui.h文件添加到我们的项目中。此外,我们还需要添加ImGui的源码所在目录到项目的包含目录中。

步骤二:初始化ImGui

在启动应用程序时,我们需要初始化ImGui库,并创建一个ImGui的窗口。以下是初始化ImGui的代码:


IMGUI_CHECKVERSION();

ImGui::CreateContext();

ImGuiIO& io = ImGui::GetIO(); (void)io;

ImGui::StyleColorsDark();

ImGui_ImplWin32_Init(hwnd); // hwnd为窗口句柄

ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);

在以上代码中,IMGUI_CHECKVERSION() 用于检查当前ImGui的版本号,ImGui::CreateContext() 用于创建一个ImGui的上下文。接下来,我们设置ImGui的颜色主题为暗色,可以根据个人喜好设置。

最后,我们需要调用 ImGui_ImplWin32_Init(hwnd) 和 ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext) 初始化ImGui窗口,其中hwnd为窗口句柄,g_pd3dDevice和g_pd3dDeviceContext分别为D3D设备和D3D设备上下文。

步骤三:绘制血条

接下来,我们需要编写代码来绘制我们的血条。我们可以使用ImGui的ImDrawList类来绘制我们的血条。以下是绘制血条的代码:


ImGuiIO& io = ImGui::GetIO();

ImDrawList* draw_list = ImGui::GetWindowDrawList();

ImVec2 p = ImGui::GetCursorScreenPos();

const float percent = 0.65f;

const ImVec2 size = ImVec2(100, 8);

const ImVec4 filled_color = ImVec4(0.4f, 0.8f, 0.4f, 1.0f);

const ImVec4 unfilled_color = ImVec4(0.8f, 0.4f, 0.4f, 1.0f);

draw_list->AddRectFilled(p, ImVec2(p.x + size.x, p.y + size.y), unfilled_color, 4.0f);

draw_list->AddRectFilled(p, ImVec2(p.x + size.x * percent, p.y + size.y), filled_color, 4.0f);

在以上代码中,我们首先获取ImGui的IO对象,并获取窗口的绘制列表。接着,我们获取窗口当前位置,可以将血条绘制在窗口的上下文中。我们使用percent变量来控制血条的填充百分比,size变量控制血条的大小,filled_color和unfilled_color分别表示血条填充部分和未填充部分的颜色。

使用AddRectFilled方法,我们可以快速的绘制一个矩形,并填充其颜色。最后一个参数为矩形的圆角值。

步骤四:渲染ImGui窗口

最后一步是渲染ImGui窗口,我们需要在主循环中调用以下代码:


ImGui_ImplDX11_NewFrame();

ImGui_ImplWin32_NewFrame();

ImGui::NewFrame();

// 在这里绘制我们的UI元素

DrawHealthBar();

ImGui::Render();

ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

在以上代码中,我们首先调用三个函数初始化ImGui的新一帧。接着,我们绘制我们的UI元素,也就是我们的血条,在本例中是通过DrawHealthBar()函数来绘制的。最后,我们调用 ImGui::Render() 和 ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()) 渲染ImGui窗口。

完整代码示例:


#include "imgui.h"

#include "imgui_impl_dx11.h"

#include "imgui_impl_win32.h"

#include <d3d11.h>

#include <Windows.h>

void DrawHealthBar()

{

  ImGuiIO& io = ImGui::GetIO();

  ImDrawList* draw_list = ImGui::GetWindowDrawList();

  ImVec2 p = ImGui::GetCursorScreenPos();

  const float percent = 0.65f;

  const ImVec2 size = ImVec2(100, 8);

  const ImVec4 filled_color = ImVec4(0.4f, 0.8f, 0.4f, 1.0f);

  const ImVec4 unfilled_color = ImVec4(0.8f, 0.4f, 0.4f, 1.0f);

  draw_list->AddRectFilled(p, ImVec2(p.x + size.x, p.y + size.y), unfilled_color, 4.0f);

  draw_list->AddRectFilled(p, ImVec2(p.x + size.x * percent, p.y + size.y), filled_color, 4.0f);

}

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

  if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))

    return true;

  switch (msg)

  {

  case WM_PAINT:

  {

    ImGui_ImplDX11_NewFrame();

    ImGui_ImplWin32_NewFrame();

    ImGui::NewFrame();

    // 在这里绘制我们的UI元素

    DrawHealthBar();

    ImGui::Render();

    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

    ValidateRect(hWnd, NULL);

  }

  break;

  case WM_DESTROY:

    ::PostQuitMessage(0);

    break;

  default:

    return ::DefWindowProc(hWnd, msg, wParam, lParam);

  }

  return false;

}

int main()

{

  // 创建窗口

  WNDCLASS wc = { 0 };

  wc.lpfnWndProc = WndProc;

  wc.hInstance = ::GetModuleHandle(NULL);

  wc.lpszClassName = "ImGui Example";

  ::RegisterClass(&wc);

  HWND hwnd = ::CreateWindow(wc.lpszClassName,

    "ImGui Example",

    WS_OVERLAPPEDWINDOW,

    100, 100,

    640, 480,

    NULL,

    NULL,

    wc.hInstance,

    NULL);

  // 初始化D3D设备和ImGui

  ID3D11Device* g_pd3dDevice = NULL;

  ID3D11DeviceContext* g_pd3dDeviceContext = NULL;

  DXGI_SWAP_CHAIN_DESC sd;

  ZeroMemory(&sd, sizeof(sd));

  sd.BufferCount = 1;

  sd.BufferDesc.Width = 640;

  sd.BufferDesc.Height = 480;

  sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

  sd.BufferDesc.RefreshRate.Numerator = 60;

  sd.BufferDesc.RefreshRate.Denominator = 1;

  sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

  sd.OutputWindow = hwnd;

  sd.SampleDesc.Count = 1;

  sd.SampleDesc.Quality = 0;

  sd.Windowed = TRUE;

  D3D_FEATURE_LEVEL feature_level;

  DXGI_SWAP_EFFECT swap_effect;

  if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &feature_level, &g_pd3dDeviceContext) == S_OK)

    swap_effect = DXGI_SWAP_EFFECT_DISCARD;

  else if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &feature_level, &g_pd3dDeviceContext) == S_OK)

    swap_effect = DXGI_SWAP_EFFECT_FLIP_DISCARD;

  else

    return 1;

  if (!ImGui_ImplWin32_Init(hwnd)) return 1;

  if (!ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext)) return 1;

  // 显示窗口

  ShowWindow(hwnd, SW_SHOWDEFAULT);

  UpdateWindow(hwnd);

  // 进入主循环

  MSG msg;

  ZeroMemory(&msg, sizeof(msg));

  while (msg.message != WM_QUIT)

  {

    if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))

    {

      ::TranslateMessage(&msg);

      ::DispatchMessage(&msg);

      continue;

    }

  }

  // 清理ImGui

  ImGui_ImplDX11_Shutdown();

  ImGui_ImplWin32_Shutdown();

  ImGui::DestroyContext();

  // 清理D3D设备和窗口

  if (g_pd3dDeviceContext) g_pd3dDeviceContext->ClearState();

  if (g_pSwapChain) g_pSwapChain->Release();

  if (g_pd3dDeviceContext) g_pd3dDeviceContext->Release();

  if (g_pd3dDevice) g_pd3dDevice->Release();

  DestroyWindow(hwnd);

  ::UnregisterClass(wc.lpszClassName, wc.hInstance);

  return 0;

}

总结

本文介绍了如何使用C++和ImGui实现血条界面,并提供了一段示例代码。通过本文的学习,希望可以帮助大家更好地掌握ImGui的使用方法和技巧,加快游戏开发的速度和效率。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复