Повышение эффективности обнаружения столкновений (C# XNA)

Я довольно неопытный программист, в настоящее время изучаю C# и пытаюсь изучить игровой дизайн в целом.

Я использую платформу Microsoft XNA для создания игры Scrolling Shooter в стиле Galaga. После нескольких грубых испытаний, в которых я боролся с дрянной структурой ООП, делая несколько неудачных дизайнерских решений, я, наконец, добился достойного запуска двигателя.

В настоящее время у меня проблемы с обнаружением столкновений, чтобы игра не тормозила. Мой текущий движок хранит все активные игровые объекты в объекте List и циклически перебирает каждый из них, проверяя, не сталкивается ли он с другим объектом. Излишне говорить, что это может быть намного лучше.

Вот моя проверка столкновений, выполненная в классе ObjectHandler.

public override void Update(GameTime gameTime)
    {
    ...
        //Handle collisions
        foreach (GameObject obj in Objects)
        {
            ICollideable e = obj as ICollideable;
            //Check if the object implements ICollideable
            if (e != null)
            {
                //Check collision with each other object
                foreach (GameObject obj2 in Objects)
                {
                    //Check if the second object implements ICollideable
                    ICollideable e2 = obj2 as ICollideable;
                    //check if they are in the same sector
                    if (e2 != null && SameSector(e.Sector,e2.Sector))
                    {
                        //Check if the collision masks interesect
                        //if so call each object's collision event
                        if (e.Mask.Intersects(e2.Mask))
                        {
                            e.CollisionEvent(e2);
                            e2.CollisionEvent(e);
                        }
                    }
                }
            }
        }
      ...
    }

Вот функция SameSector.

private bool SameSector(Point p1, Point p2)
    {
        if (Math.Abs(p1.X-p2.X)<=1 && Math.Abs(p1.Y-p2.Y)<=1)
            return true;
        else 
            return false;
    }

«Маска» здесь — это объект Rectangle, который является частью среды XNA. Как видите, я реализовал своего рода систему пространственного разбиения, в которой каждый объект определяет, в каком квадрате 60x60 он находится. два объекта находятся в одном и том же секторе (или соседних секторах), чтобы проверить, не сталкиваются ли они.

Я уже видел вопрос, похожий на этот, но он не совсем удовлетворил мой вопрос. Из него я сделал вывод, что система тайм-менеджмента полезна. В конце концов я попытаюсь реализовать это, но, поскольку я все еще новичок в программировании, я хотел бы оптимизировать саму проверку столкновений, прежде чем углубляться в более продвинутый дизайн.

Итак, есть ли способ эффективно оптимизировать текущую проверку столкновений, или это то, с чего мне нужно начать?


person Shiny Chocobo    schedule 29.04.2012    source источник


Ответы (1)


Пространственное разбиение поможет вам только в том случае, если вы реализовали его таким образом, что вам не требуется каким-либо образом сравнивать каждый объект с каждым объектом.

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

Я настоятельно рекомендую книгу Обнаружение столкновений в реальном времени который подробно описывает несколько различных схем широкофазного разделения, а также их относительные сильные и слабые стороны, в дополнение к другим темам компакт-диска. В дополнение к однородным сеткам существуют иерархические сетки, деревья квадрантов, развертка и обрезка и другие методы, которые могут быть вам более подходящими (подметание и удаление может быть особенно полезным).

person Justin Aquadro    schedule 29.04.2012