效果视频
前情回顾
手把手教你开发一款方框透视外挂【已完结】
FPS方框透视辅助开发教学1:数据挖掘和基本绘制
https://www.52xuejishu.com/forum-post/337.html
FPS方框透视辅助开发教学2:编写代码读取玩家数据
https://www.52xuejishu.com/forum-post/339.html
FPS方框透视辅助开发教学3:屏幕坐标转换算法、绘制文本到敌人
https://www.52xuejishu.com/forum-post/340.html
FPS方框透视辅助开发教学4:屏幕坐标转换算法完整解析
https://www.52xuejishu.com/forum-post/345.html
FPS方框透视辅助开发教学5:绘制所有敌人射线和距离
https://www.52xuejishu.com/forum-post/347.html
FPS方框透视辅助开发教学6:实现GDI绘制方框透视(完结)
https://www.52xuejishu.com/forum-post/349.html
想学习游戏辅助开发没地方?
来这里,我们有基础版299和专业版2024
【基础版】包含4套教学,赠送价值158过检测过保护CE
B站平台可直达下单,手机访问效果最佳
包含:
学习游戏安全,加入游戏安全逆向基础版社区,现在优惠价299
游戏安全逆向:入门科普大全解
https://study.163.com/course/courseMain.htm?courseId=1212474809&share=2&shareId=1020678503
游戏安全逆向工程师:CE基础
https://study.163.com/course/courseMain.htm?courseId=1209141829&share=2&shareId=1020678503
C语言0基础入门游戏辅助开发实践
https://study.163.com/course/courseMain.htm?courseId=1213365801&share=2&shareId=1020678503
易语言0基础游戏辅助电脑脚本开发(正在更新ing)
https://study.163.com/course/courseMain.htm?courseId=1213780852&share=2&shareId=1020678503
优惠下单链接,学习游戏修改作弊、辅助脚本开发、飞天遁地透视自瞄辅助技术,您的最佳选择:
平台下单地址https://mall.bilibili.com/neul-next/detailuniversal/detail.html?isMerchant=1&page=detailuniversal_detail&saleType=10&itemsId=11262567&loadingShow=1&noTitleBar=1
下单后承诺以上四套内容全部开通在网易云课堂、永久观看时效、指导答疑
下单后即赠送过网络游戏检测保护的CE游戏修改器一套(价值158)
【专业版】包含12套教学,内容更多,工具更丰富,详情联系i-xiaodi
初识D3D9
Direct3D 9(简称 D3D9)是微软推出的 DirectX API 的一部分,主要用于在 Windows 平台上进行 3D 图形渲染。它为开发者提供了操作图形硬件的接口,以实现复杂的 3D 图形效果。广泛应用于需要高性能图形处理的领域,如游戏开发。当然,也被很多人用于外挂开发。
D3D9绘制的基本流程:
- 初始化Direct3D对象: 首先,通过
Direct3DCreate9
函数创建IDirect3D9
接口的实例,这是进行后续操作的基础。 - 设置显示参数: 定义
D3DPRESENT_PARAMETERS
结构体,设置窗口模式、后台缓冲区格式、交换效果等参数,以配置显示模式。 - 创建设备对象: 使用
IDirect3D9
的CreateDevice
方法创建IDirect3DDevice9
接口实例,设备对象用于管理资源并执行渲染操作。 - 设置渲染状态: 配置渲染状态,包括光照、混合模式、深度测试等,以控制图形的渲染方式。
- 创建并设置顶点缓冲区: 定义顶点数据并创建顶点缓冲区,将顶点数据加载到缓冲区中。然后,设置顶点格式并将缓冲区绑定到设备。
- 渲染循环: 在主循环中,执行以下步骤:
-
- 清除缓冲区: 使用
Clear
方法清除渲染目标和深度缓冲区。 - 开始场景: 调用
BeginScene
方法开始绘制场景。 - 绘制图元: 使用
DrawPrimitive
或DrawIndexedPrimitive
方法绘制基本图元,如三角形、线条等。 - 结束场景: 调用
EndScene
方法结束场景绘制。 - 显示结果: 使用
Present
方法将渲染结果显示到屏幕上。
- 清除缓冲区: 使用
- 释放资源: 在程序结束时,释放所有分配的资源,包括设备、缓冲区等,以避免内存泄漏。
示例:绘制一个实心矩形
#include <windows.h>
#include <d3d9.h>
#pragma comment(lib, "d3d9.lib")
// 全局变量
LPDIRECT3D9 g_pD3D = nullptr; // Direct3D接口
LPDIRECT3DDEVICE9 g_pd3dDevice = nullptr; // Direct3D设备
LPDIRECT3DVERTEXBUFFER9 g_pVB = nullptr; // 顶点缓冲区
// 定义灵活顶点格式(屏幕坐标,预变换)
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
// 定义顶点结构体
struct CUSTOMVERTEX
{
float x, y, z, rhw; // 位置及齐次坐标
DWORD color; // 颜色
};
// 窗口过程
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
// 初始化 Direct3D
bool InitD3D(HWND hwnd)
{
// 创建 Direct3D 接口
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_pD3D == nullptr)
return false;
// 设置呈现参数
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE; // 窗口模式
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 丢弃交换链
d3dpp.hDeviceWindow = hwnd; // 指定渲染窗口
// 创建 Direct3D 设备
if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pd3dDevice)))
{
return false;
}
return true;
}
// 初始化几何数据(顶点缓冲区),绘制一个矩形
bool InitGeometry()
{
// 创建顶点缓冲区,包含4个顶点
if (FAILED(g_pd3dDevice->CreateVertexBuffer(4 * sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&g_pVB,
nullptr)))
{
return false;
}
// 填充顶点数据
CUSTOMVERTEX* pVertices;
if (FAILED(g_pVB->Lock(0, 4 * sizeof(CUSTOMVERTEX), (void**)&pVertices, 0)))
{
return false;
}
// 设置矩形四个角的坐标和颜色(使用预变换的屏幕坐标)
// (150,50) 左上角,(450,50) 右上角,(150,350) 左下角,(450,350) 右下角
pVertices[0] = { 150.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0) }; // 红色
pVertices[1] = { 450.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0) }; // 绿色
pVertices[2] = { 150.0f, 350.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255) }; // 蓝色
pVertices[3] = { 450.0f, 350.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 255, 0) }; // 黄色
g_pVB->Unlock();
return true;
}
// 渲染场景
void Render()
{
if (g_pd3dDevice == nullptr)
return;
// 清除屏幕背景,设置为黑色
g_pd3dDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
// 开始场景
if (SUCCEEDED(g_pd3dDevice->BeginScene()))
{
// 设置顶点缓冲区
g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
g_pd3dDevice->SetFVF(CUSTOMFVF);
// 使用三角形带绘制矩形(绘制两个三角形构成矩形)
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
// 结束场景
g_pd3dDevice->EndScene();
}
// 呈现渲染结果
g_pd3dDevice->Present(nullptr, nullptr, nullptr, nullptr);
}
// 释放资源
void Cleanup()
{
if (g_pVB != nullptr)
g_pVB->Release();
if (g_pd3dDevice != nullptr)
g_pd3dDevice->Release();
if (g_pD3D != nullptr)
g_pD3D->Release();
}
// 程序入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
// 注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX),
CS_CLASSDC,
WindowProc,
0,
0,
hInstance,
nullptr,
nullptr,
nullptr,
nullptr,
"D3D9_Rectangle_Class",
nullptr };
RegisterClassEx(&wc);
// 创建窗口
HWND hwnd = CreateWindow("D3D9_Rectangle_Class",
"D3D9 绘制矩形示例",
WS_OVERLAPPEDWINDOW,
100,
100,
800,
600,
nullptr,
nullptr,
hInstance,
nullptr);
if (hwnd == nullptr)
return 0;
// 初始化 Direct3D
if (!InitD3D(hwnd))
return 0;
// 初始化几何数据
if (!InitGeometry())
return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 消息循环
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Render();
}
}
Cleanup();
return 0;
}
以上是一个基本的框架,无论绘制什么东西,都可以遵循这个框架
示例:绘制一个透明矩形
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
LPDIRECT3D9 pD3D = nullptr; // Direct3D 对象
LPDIRECT3DDEVICE9 pD3DDevice = nullptr; // Direct3D 设备
// Direct3D 初始化函数
bool InitD3D(HWND hWnd) {
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!pD3D) {
MessageBox(hWnd, "Direct3D 初始化失败", "错误", MB_OK);
return false;
}
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE; // 窗口化
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 交换效果
d3dpp.hDeviceWindow = hWnd; // 设置窗口句柄
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // 后备缓冲区格式
// 创建设备
if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pD3DDevice))) {
MessageBox(hWnd, "创建 Direct3D 设备失败", "错误", MB_OK);
return false;
}
return true;
}
// 清理 Direct3D 资源
void Cleanup() {
if (pD3DDevice) {
pD3DDevice->Release();
pD3DDevice = nullptr;
}
if (pD3D) {
pD3D->Release();
pD3D = nullptr;
}
}
// 绘制带有外框颜色的透明矩形
void Render() {
// 清空背景
pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
pD3DDevice->BeginScene();
// 设置外框颜色为红色
D3DCOLOR borderColor = D3DCOLOR_ARGB(255, 255, 0, 0); // 红色外框
// 设置矩形的坐标和尺寸
RECT rect = { 100, 100, 400, 300 };
// 绘制矩形的外框
struct Vertex {
float x, y, z, rhw;
D3DCOLOR color;
};
Vertex vertices[] = {
{ 100.0f, 100.0f, 0.0f, 1.0f, borderColor }, // 左上
{ 400.0f, 100.0f, 0.0f, 1.0f, borderColor }, // 右上
{ 400.0f, 300.0f, 0.0f, 1.0f, borderColor }, // 右下
{ 100.0f, 300.0f, 0.0f, 1.0f, borderColor }, // 左下
{ 100.0f, 100.0f, 0.0f, 1.0f, borderColor } // 返回左上,闭合矩形
};
// 画外框
pD3DDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
pD3DDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, vertices, sizeof(Vertex));
pD3DDevice->EndScene();
pD3DDevice->Present(NULL, NULL, NULL, NULL);
}
// Windows 窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
return 0;
case WM_SIZE:
// 处理窗口大小改变时的设备重置
if (pD3DDevice) {
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
pD3DDevice->Reset(&d3dpp);
}
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
// WinMain 入口函数
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, ("D3D9Demo"), NULL };
RegisterClassEx(&wc);
HWND hWnd = CreateWindow(wc.lpszClassName, ("透明矩形框"), WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, wc.hInstance, NULL);
if (!InitD3D(hWnd)) {
Cleanup();
return 0;
}
ShowWindow(hWnd, nCmdShow);
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);
}
else {
Render();
}
}
Cleanup();
return 0;
}
后续流程
步骤 | 操作 |
---|---|
1 | 初始化控制台信息 |
2 | 查找游戏窗口 |
3 | 创建透明覆盖窗口 |
4 | 初始化D3D9设备 |
5 | 启动数据采集线程 |
6 | 启动窗口位置跟踪线程 |
7 | 进入主消息循环 |
8 | 是否收到退出消息? |
9 | 如果是,进行资源清理 |
10 | 如果否,返回第7步继续执行 |
透视程序编写
1. 初始化 D3D
bool InitD3D(HWND hWnd) {
// 1. 创建D3D9接口对象
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
// 2. 配置呈现参数
ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
g_d3dpp.Windowed = TRUE; // 窗口模式
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;// 交换效果
g_d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;// 带Alpha通道的32位格式
g_d3dpp.EnableAutoDepthStencil = TRUE; // 启用深度模板
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;// 16位深度缓冲
// 3. 创建设备对象
HRESULT result = g_pD3D->CreateDevice(
D3DADAPTER_DEFAULT, // 默认显卡
D3DDEVTYPE_HAL, // 硬件抽象层
hWnd, // 关联窗口
D3DCREATE_HARDWARE_VERTEXPROCESSING, // 硬件顶点处理
&g_d3dpp, // 呈现参数
&g_pd3dDevice // 输出设备指针
);
// 4. 设置混合状态(透明关键)
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // 启用Alpha混合
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); // 源混合因子
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);// 目标混合因子
// 5. 创建绘图工具
D3DXCreateLine(g_pd3dDevice, &g_pLine); // 线条绘制对象
D3DXCreateFont(...); // 字体对象(省略参数)
return SUCCEEDED(result);
}
2.创建透明窗口
// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
g_bRunning = false;
PostQuitMessage(0);
return 0;
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
Render();
return 0;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
HWND CreateOverlayWindow() {
// 窗口类配置
WNDCLASSEX wc = {
.cbSize = sizeof(WNDCLASSEX),
.style = CS_HREDRAW | CS_VREDRAW, // 窗口重绘模式
.lpfnWndProc = WndProc, // 消息处理回调
.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH), // 黑色背景画刷
.lpszClassName = "D3DOverlayClass" // 唯一类名
};
// 注册窗口类
RegisterClassEx(&wc);
// 获取游戏窗口位置
RECT targetRect;
GetWindowRect(g_hTargetWnd, &targetRect);
// 创建窗口关键参数:
// WS_EX_LAYERED - 分层窗口(支持透明)
// WS_EX_TRANSPARENT - 穿透鼠标事件
// WS_EX_TOPMOST - 始终置顶
HWND hWnd = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
"D3DOverlayClass",
"Game Overlay",
WS_POPUP, // 无边框窗口
targetRect.left, // 与游戏窗口对齐
targetRect.top,
targetRect.right - targetRect.left, // 同游戏窗口宽度
targetRect.bottom - targetRect.top, // 同游戏窗口高度
nullptr, nullptr, nullptr, nullptr
);
// 设置透明色(黑色部分透明)
SetLayeredWindowAttributes(hWnd, RGB(0,0,0), 0, LWA_COLORKEY);
return hWnd;
}
3. 数据采集线程工作流程
void DataThread() {
// 1. 获取游戏进程信息
DWORD pid = GetProcessID("hl.exe");
DWORD moduleBase = GetModuleBase(pid, "amxmodx_mm.dll");
// 2. 打开进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
while(running) {
// 3. 读取本地玩家数据
ReadProcessMemory(hProcess, (LPCVOID)characterBase, &localPlayerAddr, 4, 0);
ReadProcessMemory(hProcess, positionAddr, &myX, 4, 0);
// 4. 遍历所有实体
for(DWORD i = 1; i < playerCount; ++i) {
// 5. 读取敌人数据
ReadProcessMemory(hProcess, enemyAddr + HEALTH_OFFSET, &health, 4, 0);
// 6. 执行核心算法计算屏幕坐标
float dx = enemyX - myX;
// ...(象限判断、角度计算等)...
// 7. 存储有效敌人信息
newEnemies.push_back({screenX, screenY, ...});
}
// 8. 线程安全更新数据
std::lock_guard<std::mutex> lock(g_dataMutex);
g_enemies = std::move(newEnemies);
}
}
4. 渲染管线工作流程
void Render() {
// 1. 检查设备状态
if(g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICELOST) {
Sleep(100); // 设备丢失时等待恢复
return;
}
// 2. 清空后台缓冲(使用完全透明色)
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 1.0f, 0);
if(SUCCEEDED(g_pd3dDevice->BeginScene())) {
// 3. 加锁访问共享数据
std::lock_guard<std::mutex> lock(g_dataMutex);
// 4. 遍历所有敌人进行绘制
for(const auto& enemy : g_enemies) {
if (enemy.inView) {
// 绘制方框
D3DDrawBorderBox(
enemy.screenX - 20.0f,
enemy.screenY,
enemy.boxWidth,
enemy.boxHeight,
2,
D3DCOLOR_XRGB(0, 206, 209));
// 绘制指示线
D3DDrawLine(
512.0f, // 开始屏幕X坐标
0.0f, // 开始屏幕Y坐标
enemy.screenX + enemy.boxWidth / 2 - 20.f, // endX
enemy.screenY, // endY (可调整垂直偏移)
2.0f, // width
D3DCOLOR_XRGB(0, 206, 209)
);
}
}
// 5. 结束场景提交绘制
g_pd3dDevice->EndScene();
}
// 6. 呈现到屏幕
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}
5.辅助绘制:画框、画线、写字
//画框
void D3DDrawBorderBox(float x, float y, float w, float h, float thickness, D3DCOLOR color)
{
// 顶部横线
D3DRECT rect = { (LONG)x, (LONG)y, (LONG)(x + w), (LONG)(y + thickness) };
g_pd3dDevice->Clear(1, &rect, D3DCLEAR_TARGET, color, 0, 0);
// 左侧竖线
rect = { (LONG)x, (LONG)y, (LONG)(x + thickness), (LONG)(y + h) };
g_pd3dDevice->Clear(1, &rect, D3DCLEAR_TARGET, color, 0, 0);
// 右侧竖线
rect = { (LONG)(x + w - thickness), (LONG)y, (LONG)(x + w), (LONG)(y + h) };
g_pd3dDevice->Clear(1, &rect, D3DCLEAR_TARGET, color, 0, 0);
// 底部横线
rect = { (LONG)x, (LONG)(y + h - thickness), (LONG)(x + w), (LONG)(y + h) };
g_pd3dDevice->Clear(1, &rect, D3DCLEAR_TARGET, color, 0, 0);
}
//画线
void D3DDrawLine(float x1, float y1, float x2, float y2, float width, D3DCOLOR color)
{
if (!g_pLine) return;
D3DXVECTOR2 points[] = {
D3DXVECTOR2(x1, y1),
D3DXVECTOR2(x2, y2)
};
g_pLine->SetWidth(width);
g_pLine->Draw(points, 2, color);
}
//画字
void D3DDrawString(float x, float y, D3DCOLOR color, const char* text)
{
RECT rect = {
static_cast<LONG>(x),
static_cast<LONG>(y),
static_cast<LONG>(x + 100),
static_cast<LONG>(y + 20)
};
g_pFont->DrawTextA(NULL, text, -1, &rect, DT_LEFT | DT_NOCLIP, color);
}
6.取进程 ID 和模块句柄函数封装
//获取进程ID
DWORD GetProcessID(const char* processName) {
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
if (Process32First(snapshot, &entry)) {
do {
if (_stricmp(entry.szExeFile, processName) == 0) {
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
}
CloseHandle(snapshot);
return 0;
}
//获取模块句柄
DWORD GetModuleBase(DWORD pid, const char* moduleName) {
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
MODULEENTRY32 entry = { sizeof(MODULEENTRY32) };
if (Module32First(snapshot, &entry)) {
do {
if (_stricmp(entry.szModule, moduleName) == 0) {
CloseHandle(snapshot);
return (DWORD)entry.modBaseAddr;
}
} while (Module32Next(snapshot, &entry));
}
CloseHandle(snapshot);
return 0;
}
7.透明窗口跟随游戏
HWND gameHwnd = nullptr; // 游戏窗口句柄
// 更新窗口位置
void UpdateOverlayPosition() {
RECT gameRect;
while (true) {
if (gameHwnd && GetWindowRect(gameHwnd, &gameRect)) {
// 移动透明窗口
SetWindowPos(g_hOverlayWnd, nullptr, gameRect.left, gameRect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
Sleep(10); // 适当降低CPU占用
}
}
// 在创建透明窗口后调用
void StartOverlay(HWND game) {
gameHwnd = game;
std::thread(UpdateOverlayPosition).detach(); // 启动线程
}
8.入口函数和提示提醒
void PrintWelcomeMessage() {
SetConsoleTitleA("《终极游戏辅助》 v1.0 微信i-xiaodi B站:小迪xiaodi老师 学技术网:www.52xuejishu.com");
// 获取当前时间
std::time_t now = std::time(nullptr);
std::tm* localTime = std::localtime(&now);
// 打印欢迎信息
std::cout << "**********************************************************\n";
std::cout << "* *\n";
std::cout << "* 欢迎使用《终极游戏辅助》 v1.0 *\n";
std::cout << "* *\n";
std::cout << "**********************************************************\n";
std::cout << "\n";
std::cout << "当前时间:"
<< (1900 + localTime->tm_year) << "年"
<< (1 + localTime->tm_mon) << "月"
<< localTime->tm_mday << "日 "
<< localTime->tm_hour << ":"
<< localTime->tm_min << ":"
<< localTime->tm_sec << "\n";
std::cout << "\n";
std::cout << "本辅助仅供娱乐使用,严禁用于非法用途。\n";
std::cout << "功能简介:\n";
std::cout << "1. 方框透视\n";
std::cout << "2. 显示敌人位置\n";
std::cout << "\n";
std::cout << "祝您游戏愉快,玩的开心!\n";
std::cout << "\n";
}
int main() {
//打印辅助提醒信息
PrintWelcomeMessage();
// 查找目标窗口
g_hTargetWnd = FindWindow("Valve001", "Counter-Strike");
if (!g_hTargetWnd) {
return 1;
}
// 创建覆盖窗口
g_hOverlayWnd = CreateOverlayWindow();
if (!g_hOverlayWnd || !InitD3D(g_hOverlayWnd)) {
return 1;
}
ShowWindow(g_hOverlayWnd, SW_SHOW);
// 启动数据线程
std::thread dataThread(DataThread);
// 检测窗口变动
StartOverlay(g_hTargetWnd);
// 主消息循环
MSG msg;
while (g_bRunning) {
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
// 触发持续渲染
InvalidateRect(g_hOverlayWnd, nullptr, FALSE);
UpdateWindow(g_hOverlayWnd);
Sleep(1);
}
}
// 清理资源
dataThread.join();
if (g_pLine) g_pLine->Release();
if (g_pFont) g_pFont->Release();
if (g_pd3dDevice) g_pd3dDevice->Release();
if (g_pD3D) g_pD3D->Release();
return 0;
}
9.其他的一些声明和定义
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <tlhelp32.h>
#include <vector>
#include <mutex>
#include <cmath>
#include <string>
#include <iostream>
#include <string>
#include <ctime>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dwmapi.lib")
// 常量定义
constexpr DWORD PLAYER_BASE_OFFSET = 0x97030; //玩家基址模块偏移
constexpr DWORD PLAYER_COUNT_OFFSET = 0x96184;//房间人数偏移
constexpr DWORD ENTITY_LIST_OFFSET = 0x230;//人物遍历差值(偏移)
constexpr DWORD TEAM_OFFSET = 0x134;//阵营偏移
constexpr DWORD HEALTH_OFFSET = 0x1E0;//血量偏移
constexpr DWORD POSITION_OFFSET = 0x88;//坐标偏移
constexpr DWORD VIEW_ANGLE_X_OFFSET = 0x19E10C8;//鼠标X
constexpr DWORD VIEW_ANGLE_Y_OFFSET = 0x19E10C4;//鼠标Y
// 玩家信息
struct EnemyInfo {
float screenX;
float screenY;
float boxWidth;
float boxHeight;
bool inView;
};
LPDIRECT3D9 g_pD3D = nullptr;
LPDIRECT3DDEVICE9 g_pd3dDevice = nullptr;
D3DPRESENT_PARAMETERS g_d3dpp = {};
LPD3DXFONT g_pFont = NULL;
ID3DXLine* g_pLine = nullptr;
HWND g_hTargetWnd = nullptr;
HWND g_hOverlayWnd = nullptr;
std::vector<EnemyInfo> g_enemies;
std::mutex g_dataMutex;
bool g_bRunning = true;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool InitD3D(HWND);
HWND CreateOverlayWindow();
void DataThread();
void Render();
DWORD GetProcessID(const char*);
DWORD GetModuleBase(DWORD, const char*);
结语
至此,我们就完成了一款FPS游戏的D3D方框透视
是否还有其他好玩的东西?
当然是有的,比如添加绘制的菜单,绘制血量等
菜单还可以使用第三方库比如ImGui
有很多东西等着大家去拓展,以后有时间我们再更新~
没有回复内容