Обнаружение столкновений в 2D-игре без тайлов XNA

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

Я много думал об этом, и в голову пришло несколько идей:

-Один большой прямоугольник вокруг всего уровня и один вокруг персонажа с использованием идеального столкновения пикселей. Но я не думаю, что это сработает, поскольку прямоугольник также будет включать фон.

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

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

-Используйте коллизионный двигатель. Я бы предпочел сделать игру с нуля.

Прошу прощения, если я плохо объяснил, но это довольно сложная проблема (по крайней мере для меня), и я не могу найти никакого решения в сети. Буду очень рад любым идеям, спасибо.


person user3313308    schedule 15.02.2014    source источник


Ответы (1)


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

Персонаж (розовый БГ прозрачный :)

введите описание изображения здесь

Пещера (белый прозрачен)

введите описание изображения здесь

Задний план:

введите описание изображения здесь

Все три сложены вместе:

введите описание изображения здесь

Это просто для того, чтобы дать вам очень приблизительное представление (так как я только что погуглил фон и нарисовал пещеру краской). Затем вы можете использовать обнаружение столкновения альфа-пикселей между текстурой пещеры (НЕ фоном пещеры) и текстурой персонажа. См. this, чтобы узнать, как можно легко использовать попиксельную коллизию. HTH. Вот код столкновения, который вы могли бы использовать (rectangleA должен быть прямоугольником персонажа, dataA пиксельными данными персонажа, rectangleB прямоугольником пещеры (который, вероятно, будет весь экран) и dataB данные пикселей пещеры (НЕ ФОН )) Поскольку вы не используете пиксельные данные фонового изображения, столкновение не будет проверяться с помощью этих данных:

    /// <param name="rectangleA">Bounding rectangle of the first sprite</param>
    /// <param name="dataA">Pixel data of the first sprite</param>
    /// <param name="rectangleB">Bouding rectangle of the second sprite</param>
    /// <param name="dataB">Pixel data of the second sprite</param>
    /// <returns>True if non-transparent pixels overlap; false otherwise</returns>
    static bool IntersectPixels(Rectangle rectangleA, Color[] dataA,
                                Rectangle rectangleB, Color[] dataB)
    {
        // Find the bounds of the rectangle intersection
        int top = Math.Max(rectangleA.Top, rectangleB.Top);
        int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
        int left = Math.Max(rectangleA.Left, rectangleB.Left);
        int right = Math.Min(rectangleA.Right, rectangleB.Right);

        // Check every point within the intersection bounds
        for (int y = top; y < bottom; y++)
        {
            for (int x = left; x < right; x++)
            {
                // Get the color of both pixels at this point
                Color colorA = dataA[(x - rectangleA.Left) +
                                     (y - rectangleA.Top) * rectangleA.Width];
                Color colorB = dataB[(x - rectangleB.Left) +
                                     (y - rectangleB.Top) * rectangleB.Width];

                // If both pixels are not completely transparent,
                if (colorA.A != 0 && colorB.A != 0)
                {
                    // then an intersection has been found
                    return true;
                }
            }
        }

        // No intersection found
        return false;
    }
person davidsbro    schedule 15.02.2014
comment
@ user3313308, это помогло? - person davidsbro; 16.02.2014
comment
Спасибо за ответ @davidsbro! Мне все еще нужно размещать прямоугольники, чтобы было столкновение пиксель на пиксель, верно? Или я неправильно понял концепцию попиксельного столкновения? Если я правильно понял, он проверяет, не сталкиваются ли два прямоугольника, а затем проверяет цвета внутри прямоугольников, чтобы увидеть, сталкиваются ли они. Это правильно? Если это так, разве мне все равно нужно будет расставлять прямоугольники вокруг пещеры? - person user3313308; 17.02.2014
comment
Да ты прав @ user3313308. Но у вас должно быть только два прямоугольника; одна вокруг всей текстуры пещеры (которая, вероятно, будет целым экраном) и одна вокруг игрока; вам не нужно больше двух. Ссылка, которую я предоставил, представляет собой очень простой попиксельный проект столкновения, поэтому вы можете получить представление о том, на что это будет похоже. ЛМК во всяком случае непонятно. - person davidsbro; 17.02.2014
comment
Фактически, вам понадобится только один прямоугольник для персонажа, если пещера охватывает весь экран. Затем все, что вам нужно сделать, это проверить каждый пиксель (из текстуры пещеры и текстуры персонажа) в прямоугольнике персонажа. - person davidsbro; 17.02.2014
comment
Разве пиксели фона не будут включены в прямоугольник по всему экрану? Теперь я понимаю, как это сделать без фона, но если я включу фон, не будет ли он засчитан в пикселях? Спасибо, что нашли время объяснить мне! - person user3313308; 18.02.2014
comment
Нет, если вы только проверите текстуру пещеры на предмет столкновения. Прямоугольник вокруг всего экрана просто проверяет, не сталкивается ли игрок с ним (что всегда будет). Таким образом, столкновение сводится к проверке текстуры cave (а не фона) по отношению к текстуре персонажа. Конечно, я более чем рад помочь! Я добавлю код столкновения к своему ответу, чтобы помочь объяснить. - person davidsbro; 18.02.2014
comment
Думаю, теперь я понял, попробую сегодня позже, а завтра сообщу о результатах! Чего я до сих пор не понимаю: почему фон не мешает, мы нигде не упоминаем текстуру пещеры, так какая разница между фоном и текстурой пещеры, заставляющая обнаружение столкновения пропускать пиксели фона ? - person user3313308; 18.02.2014
comment
Что вам нужно сделать, так это сравнить данные пикселей из текстуры пещеры с данными из текстуры персонажа. Так как фоновая текстура отделена (или должна быть) от пещеры, фон не участвует в обнаружении столкновений. Удачи. Лмк, как дела. - person davidsbro; 18.02.2014
comment
У меня все заработало, теперь я тоже все понимаю, спасибо большое! Вы хоть знаете, как остановить персонажа, когда он пересекается? Чтобы он не застрял ... Раньше я делал только космические шутеры, поэтому я не очень хорошо знаком с этим видом программирования. - person user3313308; 19.02.2014
comment
Конечно, рада, что смогла помочь! Чтобы персонаж не застрял, вы можете попробовать переместить его назад на кадр, когда он пересекается, или запретить движение, если он пересекается, и т. Д. Также вы можете посмотреть здесь: stackoverflow.com/questions/17666507/ - person davidsbro; 19.02.2014
comment
Привет еще раз! Я пробовал уже неделю, но не могу даже приблизиться к работе. У вас есть другие ссылки, кроме этой? - person user3313308; 25.02.2014
comment
Каков твой вопрос? Буду рада помочь! Мне не известны другие ссылки, но, возможно, если вы изложите свою проблему, я смогу помочь. - person davidsbro; 26.02.2014
comment
Проблема в том, что я не могу определить, откуда произошло столкновение, если бы я знал это, я мог бы просто отодвинуть его назад, откуда он пришел. Но поскольку один из прямоугольников покрывает всю сцену, я не могу создать rectangle.top и т. Д. Кроме того, когда я пытался проверить столкновение только с одного направления (под персонажем), он тонет, а затем медленно движется вверх к в нужное место вместо телепортации туда ... Есть идеи? - person user3313308; 27.02.2014
comment
@ user3313308 Что ж, если у вашего игрока есть скорость, вы можете использовать ее, чтобы определить, откуда происходит столкновение. Или вы можете найти, где на текстуре персонажа происходит столкновение, и использовать это. Например, если пиксель столкновения находится справа от персонажа, вы знаете, что он прибыл справа. - person davidsbro; 28.02.2014