Vector 中的 1000 多个游戏对象太慢了?我的错误是啥?

Posted

技术标签:

【中文标题】Vector 中的 1000 多个游戏对象太慢了?我的错误是啥?【英文标题】:1000+ Game-Objects in Vector too slow? What is my mistake?Vector 中的 1000 多个游戏对象太慢了?我的错误是什么? 【发布时间】:2015-04-07 14:51:04 【问题描述】:

我目前正在开发一款需要跟踪大量对象的游戏。

我有一个游戏对象类,它包含对象的所有必要信息并在 update() 上处理 AI();

我决定,只有有大脑的对象才需要每帧更新。所以我分离了向量以节省时间。但是,在绘制对象时,我似乎找不到类似的解决方案。所以我得到了

std::vector<cOBJECT*> LivingObjects;

std::vector<cOBJECT*> WorldObjects;

在绘制所有对象时,我首先将所有对象放在一个RenderList中:

//Add World and Living Objects into one list of RenderObjects
RenderObjects = WorldObjects;
RenderObjects.insert(RenderObjects.end(), LivingObjects.begin(), LivingObjects.end());

然后我按 Y 对它们进行排序:

//Sort all Objects by Y (bottom) Coordiante
sort(RenderObjects.begin(), RenderObjects.end(), cmd);

这是代码(也许这也很慢?:

//Sorts by Y-Coordinaté
bool cmd(cOBJECT* obj1, cOBJECT* obj2)

    return obj1->getrect().y + obj1->getrect().h < obj2->getrect().y + obj2->getrect().h;

然后我画它们。绘图功能将检查它们是否在屏幕上!所以我只画可见的物体:

//DRAW OBJECTS and 
for (std::vector<cOBJECT*>::size_type i = 0; i != RenderObjects.size(); i++)

    RenderObjects[i]->render(Renderer, CameraX, CameraY, SCREEN_WIDTH, SCREEN_HEIGHT);

这是实际的绘制函数':

int cTEXTURES::renderAnimation(int targetX, int targetY, double angle, SDL_Point* center, SDL_RendererFlip flip, SDL_Renderer* Renderer, int row, int speed, int offX, int offY, int SCREEN_HEIGHT, int SCREEN_WIDTH)

    //Draw if part of it shown on screen
    if (targetX - offX >= -FrameWidth && targetX - offX <= SCREEN_WIDTH + FrameWidth && targetY - offY >= -FrameHeight && targetY - offY <= SCREEN_HEIGHT + FrameHeight)
    
        SDL_Rect SourceRect;
        SDL_Rect TargetRect;

        TargetRect =  targetX - offX, targetY - offY, FrameWidth, FrameHeight ;

        SourceRect.x = (CurrentFrame - 1) * FrameWidth;
        SourceRect.y = (row - 1) * FrameHeight;
        SourceRect.w = FrameWidth;
        SourceRect.h = FrameHeight;

        if (OldTime + speed > SDL_GetTicks())  SDL_RenderCopyEx(Renderer, TheTextureManager::Instance()->TextureList[TexturePath], &SourceRect, &TargetRect, angle, center, flip); return 0; 

        OldTime = SDL_GetTicks();

        //SDL_RenderCopyEx(Renderer, TheTextureManager::Instance()->TextureList[TexturePath], &SourceRect, &TargetRect, angle, center, flip);
        TheTextureManager::Instance()->draw(TexturePath, Renderer, &SourceRect, &TargetRect, angle, center, flip);
        CurrentFrame++;

        if (CurrentFrame == (Frames + 1))
        
            CurrentFrame = 1;
            return 1; // returns 1 if one row is finished
        

        return 0; // returns 0 if animation is not finished
    
    return 0;

现在我得到了 1000 多个对象,以后可能还会有 2000 多个。仅仅通过for循环来检查是否需要绘制对象是非常耗时的,对吧?

我错过了什么?如何在没有大量 CPU 工作的情况下跟踪 1000 多个对象并知道是否要绘制它们?尤其是因为我需要大量空间来容纳大量 AI

谢谢,这让我发疯了。

【问题讨论】:

你能介绍一下你的程序吗? @Axalo:我正在使用 Visual C++ Express。据我所知,它不允许我这样做。 正在测量发布版本,对吧? @Angew 天哪!现在我得到了 700 FPS 和 1000 多个对象。请告诉我,这究竟是怎么发生的?调试这么慢?谢谢 简而言之:调试旨在实现源代码和二进制文件之间最接近的对应关系(以便您可以知道正在执行哪个语句),并且有大量的安全检查(空智能指针取消引用,所有本地变量都已初始化,边界检查等)。发布是针对执行速度而排除其他一切的。 【参考方案1】:

为了在调试构建中加速 stl 容器的迭代器(以及由于标头解析导致的编译时间),在包含其他任何内容(例如“windows.h”标头)之前,在第一个标头(或预编译标头)中包含以下行):

#ifdef _WIN32
#   define _CRT_SECURE_NO_WARNINGS  // disable the Microsoft specific warnings about _s buffer underrun security issues for ISO methods (fopen, strcpy etc..)
#   define VC_EXTRALEAN             // cut down includes
#   define WIN32_LEAN_AND_MEAN      // cut down includes
#   undef _SECURE_SCL               // iterators generate less overhead code in debug
#   if _ITERATOR_DEBUG_LEVEL > 0
#       define _SECURE_SCL 1
#   else
#       define _SECURE_SCL 0
#   endif
#endif

如果您链接到具有不同 iterator_debug_level 的其他库,则 _iterator_debug_level 设置可能会有点棘手。

这将使您的调试构建运行得更快,但如果需要性能,通常需要重新审视容器的使用,如果您的操作复杂或最终滚动自己的容器是最后的手段具体的。

【讨论】:

以上是关于Vector 中的 1000 多个游戏对象太慢了?我的错误是啥?的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL join 获取表中的所有行,太慢了

iPad 中的洪水填充太慢了

setFormulaArray 太慢了

Linq to Entity Paging with large dataset太慢了

Rabin Karp 在 Ruby 中的实现太慢了

Sencha 应用在 IOS 和 Android 上太慢了