我为一个名为Assault Cube的开源射击游戏写了一个目标机器人。以下是源代码的一部分:
Main.h:
/*
Control + 0 = enable aimbot
Control + 9 = enable vacuum hack
*/
#include "stdafx.h"
#ifndef MAIN_H
#define MAIN_H
#include "Player.h"
#include "Constants.h"
#include "Calculations.h"
#include <math.h>
Player players[32]; // need to give access to this to Calculations
int main() {
bool aimbotEnabled = false;
bool vacEnabled = false;
Player* closestTargetPointer = nullptr;
// [Base + DF73C] = Player 1 base
players[0] = Player(reinterpret_cast<char**>(Constants::baseAddress + 0xDF73C));
char** extraPlayersBase = *(reinterpret_cast<char***>(Constants::baseAddress + 0xE5F00));
// [Base + E5F00] = A
// [A + 0,4,8...] = Player 2/3/4... base
for (int i = 0; i < Calculations::getNumberOfPlayers() - 1; i++) {
players[i + 1] = Player(extraPlayersBase + i * 4);
}
while (true) {
if (GetAsyncKeyState(VK_CONTROL)) {
if (GetAsyncKeyState('0')) {
aimbotEnabled = !aimbotEnabled;
Sleep(500);
} else if (GetAsyncKeyState('9')) {
vacEnabled = !vacEnabled;
Sleep(500);
}
}
if (aimbotEnabled) {
closestTargetPointer = Calculations::getClosestTarget();
if (closestTargetPointer != nullptr) {
players[0].setCrosshairX(Calculations::getCrosshairHorizontalAngle(players[0], *closestTargetPointer));
players[0].setCrosshairY(Calculations::getCrosshairVerticalAngle(players[0], *closestTargetPointer));
}
}
if (vacEnabled) {
for (int i = 1; i < Calculations::getNumberOfPlayers(); i++) {
players[i].setX(players[0].getX() + 10);
players[i].setY(players[0].getY());
players[i].setZ(players[0].getZ());
}
}
Sleep(10);
}
}
#endif
Calculations.h:
#include "stdafx.h"
#ifndef CALCULATIONS_H
#define CALCULATIONS_H
#include "Player.h"
#include "Constants.h"
namespace Calculations {
/* Pythagorean's theorem applied twice for getting distance between two players in 3D space */
float getDistanceBetween(Player one, Player two) {
return sqrt(
(one.getX() - two.getX()) * (one.getX() - two.getX())
+ (one.getY() - two.getY()) * (one.getY() - two.getY())
+ (one.getZ() - two.getZ()) * (one.getZ() - two.getZ())
);
}
int getNumberOfPlayers() {
return *(reinterpret_cast<int*>(Constants::baseAddress + 0xE4E10));
}
Player* getClosestTarget() {
float smallestDistance;
int index = -1;
for (int i = 1; i < getNumberOfPlayers(); i++) {
if (players[i].getHP() > 0 && players[i].isVisible()) { // this is an error, because Calculations does not have access to the players array in Main
float tempDistance = getDistanceBetween(players[0], players[i]);
if (index == -1 || tempDistance < smallestDistance) {
smallestDistance = tempDistance;
index = i;
}
}
}
if (index == -1) {
return nullptr;
} else {
return &players[index];
}
}
float getCrosshairHorizontalAngle(Player me, Player target) {
float deltaX = target.getX() - me.getX();
float deltaY = me.getY() - target.getY();
if (target.getX() > me.getX() && target.getY() < me.getY()) {
return atanf(deltaX / deltaY) * 180.0f / Constants::pi;
} else if (target.getX() > me.getX() && target.getY() > me.getY()) {
return atanf(deltaX / deltaY) * 180.0f / Constants::pi + 180.0f;
} else if (target.getX() < me.getX() && target.getY() > me.getY()) {
return atanf(deltaX / deltaY) * 180.0f / Constants::pi - 180.0f;
} else {
return atanf(deltaX / deltaY) * 180.0f / Constants::pi + 360.0f;
}
}
float getCrosshairVerticalAngle(Player me, Player target) {
float deltaZ = target.getZ() - me.getZ();
float dist = getDistanceBetween(me, target);
return asinf(deltaZ / dist) * 180.0f / Constants::pi;
}
}
#endif
错误:
1> Calculations.h
1>Calculations.h(26): error C2065: 'players' : undeclared identifier
1>Calculations.h(26): error C2228: left of '.getHP' must have class/struct/union
1>Calculations.h(26): error C2228: left of '.isVisible' must have class/struct/union
1>Calculations.h(27): error C2065: 'players' : undeclared identifier
1>Calculations.h(39): error C2065: 'players' : undeclared identifier
所有这些错误都是因为Calculations无法访问Main中的player数组。有什么办法可以让Calculations访问玩家阵列吗?
另外,如果我将计算命名为命名空间的决定是否正确,请告诉我。
答案 0 :(得分:3)
在Calculations.h
extern Player players[32];
告诉编译器在另一个位置/文件中获取players
的定义。
extern 关键字相当于声明而不定义。这是一种显式声明变量或强制声明而没有定义的方法......
extern关键字声明一个变量或函数并指定它 它有外部链接(其名称可从除。之外的文件中看到) 一个在其中定义的)。修改变量时,extern 指定变量具有静态持续时间(在何时分配) 程序结束时程序开始并取消分配)。该 变量或函数可以在另一个源文件中定义,或者稍后定义 在同一个文件中。文件中变量和函数的声明 范围是默认的外部。
最后注意: extern 对于函数和变量的行为不相同。 more
答案 1 :(得分:2)
把:
extern Player players[32];
Calculations.h
第26行之前的某处。
答案 2 :(得分:0)
拥有一个全局播放器数组,就像使用extern关键字一样,当然不是一个好的设计决策。
更好的设计可能会定义一个世界对象,该对象了解当前存在的任何内容,并可以定义哪些参与者可以获得哪些信息。然后,玩家将查询此世界对象以获取有关其周围环境的信息,并根据该信息做出决定。
您可能希望将此世界实现为单例,以便您可以编写静态包装函数,以静默方式将对象提供给调用,从而避免在任何地方查找世界对象的麻烦。