Медленная C ++ DirectX 2D игра - PullRequest
       43

Медленная C ++ DirectX 2D игра

4 голосов
/ 29 января 2010

Я новичок в C ++ и DirectX, я из XNA. Я разработал игру типа Fly The Copter . Что я сделал, так это создал класс с именем Wall. Пока игра запущена, я рисую все стены. В XNA я хранил стены в ArrayList, а в C ++ я использовал vector. В XNA игра работает быстро, а в C ++ очень медленно. Вот код C ++:

void GameScreen::Update()
{
    //Update Walls
    int len = walls.size();
    for(int i = wallsPassed; i < len; i++)
    {
        walls.at(i).Update();
        if (walls.at(i).pos.x <= -40)
            wallsPassed += 2;
    }
}

void GameScreen::Draw()
{
    //Draw Walls
    int len = walls.size();
    for(int i = wallsPassed; i < len; i++)
    {
        if (walls.at(i).pos.x < 1280)
            walls.at(i).Draw();
        else
            break;
    }
}

В методе Update я уменьшаю значение X на 4. В методе Draw я вызываю sprite-> Draw (Direct3DXSprite). Это единственные коды, которые запускаются в игровом цикле. Я знаю, что это плохой код, если у вас есть идея улучшить его, пожалуйста, помогите. Спасибо и извините за мой английский.

Ответы [ 8 ]

8 голосов
/ 29 января 2010

Попробуйте заменить все вхождения at () на оператор []. Например:

 walls[i].Draw();

, а затем включите все оптимизации. И [], и at () являются вызовами функций - чтобы получить максимальную производительность, вам нужно убедиться, что они встроены, что и сделает повышение уровня оптимизации.

Вы также можете выполнить минимальное кэширование объекта стены - например:

 for(int i = wallsPassed; i < len; i++)
 {
    Wall & w = walls[i]; 
    w.Update();
    if (w.pos.x <= -40)
        wallsPassed += 2;
 }
2 голосов
/ 29 января 2010

Попробуйте сузить причину проблемы с производительностью (также называемой профилированием). Я бы попробовал нарисовать только один объект, продолжая обновлять все объекты. Если это внезапно быстрее, то это проблема рисования DirectX.

В противном случае попробуйте нарисовать все объекты, но обновите только одну стену. Если это быстрее, тогда ваша функция update () может быть слишком дорогой.

1 голос
/ 29 января 2010

Возможно, вы просто забыли включить режим релиза :) У меня были некоторые проблемы с ним в прошлом - я думал, что мой код был очень медленным из-за режима отладки. Если это не так, у вас могут возникнуть проблемы с рендерингом деталей или с огромным количеством объектов. Код, который вы предоставили, выглядит хорошо ...

1 голос
/ 29 января 2010
  • Как быстро 'быстро'?
  • Насколько медленный действительно медленный '?
  • Сколько спрайтов вы рисуете?
  • Насколько велика каждая из них в виде файла изображения и в пикселях, отображаемых на экране?
  • Как изменяется производительность (в XNA / C ++) при изменении количества нарисованных спрайтов?
  • Какая разница, если вы рисуете без обновления, или наоборот
0 голосов
/ 29 января 2010

Поиск в вашем списке стен вряд ли станет источником вашего замедления. Стоимость рисования объектов в 3D обычно будет ограничивающим фактором.

Важными частями являются код рисования, флаги, которые вы использовали для создания устройства DirectX, и флаги, которые вы используете для создания текстур. Мой удар в темноте ... проверьте, что вы инициализируете устройство как HAL (аппаратное обеспечение 3d), а не как REF (программное обеспечение 3d).

Кроме того, сколько спрайтов вы рисуете? Каждый колл-вызов требует значительных накладных расходов. Если вы заработаете более пары сотен за кадр, это будет вашим ограничивающим фактором.

0 голосов
/ 29 января 2010

Рисовать каждую отдельную стену с помощью другого колла - плохая идея.Попытайтесь объединить данные в один буфер вершин / индексный буфер и отправить их в одно рисование.Это более вменяемая идея.

В любом случае, чтобы получить представление о ПОЧЕМУ, он медленно работает, попробуйте с некоторыми ЦП и GPU (PerfHud, Intel GPA и т. Д.) Узнать, прежде всего, ЧТО узкое место (еслиCPU или GPU).И тогда вы можете бороться, чтобы облегчить проблему.

0 голосов
/ 29 января 2010

Вы можете помочь пакетированию вызовов отрисовки спрайтов. Предположительно, ваш вызов отрисовки вызывает ваш единственный экземпляр ID3DXSprite :: Draw с соответствующими параметрами.

Вы можете значительно повысить производительность, выполнив вызов ID3DXSprite :: Begin (с установленным флагом D3DXSPRITE_SORT_TEXTURE), а затем вызовя ID3DXSprite :: End, когда закончите рендеринг. Затем ID3DXSprite отсортирует все ваши вызовы спрайтов по текстуре, чтобы уменьшить количество переключателей текстуры, и объединит соответствующие вызовы вместе. Это значительно повысит производительность.

Трудно сказать больше, однако, не видя внутренностей ваших обновлений и вызовов Draw. Выше это только предположение ...

0 голосов
/ 29 января 2010

Вы пробовали несколько буферов (a.k.a. Double Buffering ) для растровых изображений?

Типичный сценарий - рисовать в одном буфере, затем, пока первый буфер копируется на экран, рисовать во втором буфере.

Еще один прием - иметь в памяти огромный «логический» экран. Часть изображения на физическом дисплее представляет собой область просмотра или вид в небольшую область на логическом экране. Перемещение фона (или экрана) просто требует копии со стороны графического процессора.

...