在线游戏机器人性能

时间:2019-06-07 14:30:56

标签: javascript performance bots puppeteer window-object

我正在为在线动态游戏创建机器人。在这种情况下,动态意味着英雄可以在游戏中移动并且移动时背景也在变化。像monsters这样的全局变量在移动时也会动态变化。

我的机器人正在使用puppeteer。因为我需要这个怪物对象,所以我具有每2-3秒从页面上下文中获取这些怪物的功能(随机进行反检测)。

此解决方案远非完美。两个主要缺点是:

  • 我的机器人杀死了怪物,我想转到下一个怪物,它仍然看到该怪物被杀死了,因为从该时间点开始,例如下一次刷新时间为1500ms。
  • 获得怪物的表现很差。

要解决第一个问题,我可以执行一次杀死怪物后每次下载怪物的功能。另一方面,第二个缺点将更加强大,因为我将获得更多已经很慢的怪物。

第二个问题就是性能。您可能会问,我怎么知道性能不好?

当英雄移动时,它相对平稳,但是当下载怪物时,我看到微小的滞后,例如第二次英雄停顿的一部分。也许实际上是100毫秒的延迟,但是我可以用肉眼看到它,如果我能更频繁地表演怪物,这种延迟会变得更强(请注意-延迟不会更长,但会更频繁)。

从全局窗口下载对象很长。原因是游戏维护者开发了它,使得monsters位于大对象npc中,该大对象包含仪表板中的所有内容,甚至包含空元素,因此该npc对象的总量介于100k-200k元素。为了获得最终的怪物数据,我正在做很多过滤器。

我将展示如何真正获得这些怪物。所以我执行了3个异步函数:

const allNpc = await getAllNpc(page);
let monsters = await filterMonsters(page, allNpc, monstersToHunt);
monsters.hunt = await deleteAvoidedMonsters(page, monsters.hunt, monstersToOmit);

第一个getAllNpc仅获得整个npc对象(我上面提到的这个大对象)

return await page.evaluate(() => {
    if(window.g) return g.npc;
});

第二个功能过滤实际的怪物和我想从NPC杀死的怪物:

return new Promise((resolve, reject) => {
    const validNpc = allNpc.filter(el => !!el);
    const allMonsters = validNpc.filter(e => e.lvl !== 0);

    const names = new Set(monstersNames);
    const huntMonsters = validNpc
        .filter(it => names.has(it.nick))
        .map(({ nick, x, y, grp, id }) => ({ nick, x, y, grp, id }));

    resolve({all: allMonsters, hunt: huntMonsters});
});

我在这里使用Set来摆脱O(n)/ O(n ^ 2)算法,我认为这是我可以用javascript实现的最快的速度。第三个功能与此功能相同,但额外过滤了我要避免的特殊怪物。

现在我的问题是:

  • 是否有一种方法可以在每个此对象上获取此对象,并且仅更改此对象?我知道puppeteer中有可以监视DOM变化的函数,但是有监视全局窗口对象的东西吗?
  • 我还能做些什么来加快速度吗?我在NodeJS中读过worker_threads,它可以帮助摆脱这种微小的滞后或其他问题吗?集群吗?

1 个答案:

答案 0 :(得分:0)

一段时间后,我意识到该机器人在“滞后”,因为我将这个巨大的#include <iostream> #include <cstring> #include <string> using namespace std; int main() { string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}; string key {"XZNLWEBGJHQDYVTKFUOMPCIASRxznlwebgjhqdyvtkfuompciasr"}; string word_to_encrypt {}; getline (cin,word_to_encrypt); for (int i=0;i<word_to_encrypt.size();i++){ word_to_encrypt.replace(i, 1, key, ( alphabet.find(word_to_encrypt.c_str(), i, 1)),1); } cout<< word_to_encrypt; } 数组作为函数的参数进行传递。我的意思是说我正在从g.npc解析它,然后将其传递给getAllNpc

当我对其进行更改时,我在页面上下文内的受评估脚本中的filterMonsters中执行.filter,然后解析并传递具有数百个而不是数百万个元素的数组,它的速度要快得多,并且不会导致任何滞后或冻结