C ++ OOP设计决策

时间:2013-06-15 02:22:15

标签: c++

我为一个名为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访问玩家阵列吗?

另外,如果我将计算命名为命名空间的决定是否正确,请告诉我。

3 个答案:

答案 0 :(得分:3)

Calculations.h

的开头添加
extern Player players[32];

告诉编译器在另一个位置/文件中获取players的定义。

extern 关键字相当于声明而不定义。这是一种显式声明变量或强制声明而没有定义的方法......

  

extern关键字声明一个变量或函数并指定它   它有外部链接(其名称可从除。之外的文件中看到)   一个在其中定义的)。修改变量时,extern   指定变量具有静态持续时间(在何时分配)   程序结束时程序开始并取消分配)。该   变量或函数可以在另一个源文件中定义,或者稍后定义   在同一个文件中。文件中变量和函数的声明   范围是默认的外部。

来源here(+示例)和here

最后注意: extern 对于函数和变量的行为不相同。 more

答案 1 :(得分:2)

把:

extern Player players[32];

Calculations.h第26行之前的某处。

答案 2 :(得分:0)

拥有一个全局播放器数组,就像使用extern关键字一样,当然不是一个好的设计决策。

更好的设计可能会定义一个世界对象,该对象了解当前存在的任何内容,并可以定义哪些参与者可以获得哪些信息。然后,玩家将查询此世界对象以获取有关其周围环境的信息,并根据该信息做出决定。

您可能希望将此世界实现为单例,以便您可以编写静态包装函数,以静默方式将对象提供给调用,从而避免在任何地方查找世界对象的麻烦。