Обнаружить 2d столкновение в C ++ - PullRequest
0 голосов
/ 30 ноября 2018

Мне нужно создать функцию, которая возвращает значение bool, которое будет ложным, если нет столкновения между двумя спрайтами, и истинным, если оно есть, я долго думал, и не могу найти точное решение, цель состоит в том, чтобыопределить, есть ли столкновение на пиксель, то есть если два пикселя с альфа-значением (из rgba), отличным от 0 (это видно), совпадают в одном и том же месте в пространстве, функция имеет следующую сигнатуру:

bool checkPixelCollision(
    const Vector2& pixelPos1, 
    const Vector2& pixelSize1, 
    const vector<uint8_t> pixel1, 
    const Vector2& pixelPos2, 
    const Vector2& pixelSize2, 
    const vector<uint8_t> pixel2);

Vector2 - это структура со следующей формой:

struct Vector2
{
  float x;
  float y;
};

pixelPos1 - это позиция левого верхнего угла прямоугольника, который содержит спрайт 1, pixelSize1 - это размер (x = ширина; y= высота) прямоугольника, который содержит спрайт 1, pixel1 - это вектор, который имеет значения rgba каждого пикселя спрайта, они сохраняются от 4 до 4, так что i содержит величину r пикселя i;i + 1 величина g пикселя i;i + 2 величина b пикселя i;i + 3 величина альфа пикселя i, так что если i + 3 отличается от 0, это видимый пиксель, то размер pixel1 задается как pixelSize1.x * pixelSize1.y * 4. Остальные три параметразаголовок - это заголовок, соответствующий спрайту 2. Следовательно, цель состоит в том, чтобы проверить, есть ли столкновение (на стороне или в углу), и оттуда установить прямоугольник столкновения между обоими прямоугольниками (совпадающая область) и установить два индекса.которые перемещаются pixel1 и pixel2 (поскольку каждый из них должен начинаться с другой позиции в соответствующем векторе).Проблема в том, что я не могу найти оптимальный и / или простой способ сделать это, и это работает.Если кто-нибудь знает какой-либо способ сделать это, я был бы очень признателен.

РЕДАКТИРОВАТЬ Вот мой код (он не работает)

#include <algorithm>
#include <stdint.h>
#include <vector>

struct Vector2
{
  float x;
  float y;
};

float clamp(float val, float min, float max) {
    return std::max(min, std::min(max, val));
}

bool checkPixelCollision(const Vector2& pixelPos1, const Vector2& pixelSize1, const vector<uint8_t> pixel1, const Vector2& pixelPos2, const Vector2& pixelSize2, const vector<uint8_t> pixel2) {
    return check(pixelPos1,pixelSize1,pixel1,pixelPos2,pixelSize2,pixel2)||check(pixelPos2,pixelSize2,pixel2,pixelPos1,pixelSize1,pixel1);
}

bool check(const Vector2& pixelsPos1, const Vector2& pixelsSize1, const vector<uint8_t> pixels1, const Vector2& pixelsPos2, const Vector2& pixelsSize2, const vector<uint8_t> pixels2){
    bool res = false;
    if (pixelsPos1.x <= pixelsPos2.x + pixelsSize2.x && pixelsPos1.y <= pixelsPos2.y + pixelsSize2.y && pixelsPos1.x >= pixelsPos2.x && pixelsPos1.y >= pixelsPos2.y) {
        float i = pixelsSize2.x - (pixelsSize1.y*((pixelsPos1.x - pixelsPos2.x + pixelsSize2.x) / pixelsSize1.x));
        float j = pixelsSize2.y - (pixelsSize1.y*((pixelsPos1.y - pixelsPos2.y + pixelsSize2.y) / pixelsSize1.y));
        float ifin = fmin(pixelsSize1.x - pixelsSize2.x, pixelsSize1.x);
        float jfin = fmin(pixelsSize1.y - pixelsSize2.y, pixelsSize1.y);
        float i2 = 0;
        float j2 = 0;
        while (j<jfin-1) {
            int k = floor((pixelsSize2.x*j) + i) * 4 - 1;
            int k2 = floor((pixelsSize1.x*j2) + i2) * 4 - 1;
            if (pixels1[k2 + 3] != 0 && pixels2[k + 3] != 0) {
                res = true;
            }
            if (i < ifin) {
                i = i + 1;
                i2 = i2 + 1;
            }
            else {
                i2 = 0;
                i = pixelsSize2.x - (pixelsSize1.x*((pixelsPos1.x - pixelsPos2.x + pixelsSize2.x) / pixelsSize1.x));
                j = j + 1;
                j2 = j2 + 1;
            }
        }
    }
    else if (pixelsPos1.x <= pixelsPos2.x + pixelsSize2.x && pixelsPos1.y + pixelsSize1.y >= pixelsPos2.y && pixelsPos1.x >= pixelsPos2.x && pixelsPos1.y + pixelsSize1.y <= pixelsPos2.y + pixelsSize2.y) {
        float i = clamp(pixelsSize2.x - (pixelsSize1.x*((pixelsPos1.x - pixelsPos2.x + pixelsSize2.x) / pixelsSize1.x)), 0.0f, pixelsSize2.x);
        float jfin = clamp(pixelsSize1.y*((pixelsPos2.y - pixelsPos1.y+pixelsSize1.y) / pixelsSize1.y), 0.0f, pixelsSize1.y);
        float ifin = fmin(pixelsSize1.x - pixelsSize2.x, pixelsSize1.x);
        float j = 0;
        float i2 = 0;
        float j2 = clamp(pixelsSize1.y - pixelsSize1.y*((pixelsPos2.y - pixelsPos1.y + pixelsSize1.y) / pixelsSize1.y),0.0f, pixelsSize1.y);
        while (j<jfin-1) {
            int k = floor((pixelsSize2.x*j) + i) * 4 - 1;
            int k2 = floor((pixelsSize1.x*j2) + i2) * 4 - 1;
            if (pixels1[k2 + 3] != 0 && pixels2[k + 3] != 0) {
                res = true;
            }
            if (i < ifin) {
                i = i + 1;
                i2 = i2 + 1;
            }
            else {
                i2 = 0;
                i = clamp(pixelsSize2.x - (pixelsSize1.x*((pixelsPos1.x - pixelsPos2.x + pixelsSize2.x) / pixelsSize1.x)),0.0f, pixelsSize2.x);
                j = j + 1;
                j2 = j2 + 1;
            }
        }
    }
    else if (pixelsPos1.x + pixelsSize1.x >= pixelsPos2.x && pixelsPos1.y<= pixelsPos2.y + pixelsSize2.y && pixelsPos1.x + pixelsSize1.x <= pixelsPos2.x + pixelsSize2.x && pixelsPos1.y >= pixelsPos2.y) {
        float ifin = clamp(pixelsSize1.x*((pixelsPos2.x - pixelsPos1.x + pixelsSize1.x) / pixelsSize1.x), 0.0f, pixelsSize1.x);
        float j = clamp(pixelsSize2.y - (pixelsSize1.y*((pixelsPos1.y - pixelsPos2.y + pixelsSize2.y) / pixelsSize1.y)),0.0f, pixelsSize2.y);
        float jfin = fmin(pixelsSize1.y - pixelsSize2.y, pixelsSize1.y);
        float i = 0;

        float i2 = clamp(pixelsSize1.x - pixelsSize1.x*((pixelsPos2.x - pixelsPos1.x + pixelsSize1.x) / pixelsSize1.x), 0.0f, pixelsSize1.x);
        float j2 = 0;
        while (j<jfin-1) {
            int k = floor((pixelsSize2.x*j) + i) * 4 - 1;
            int k2 = floor((pixelsSize1.x*j2) + i2) * 4 - 1;
            if (pixels1[k2 + 3] != 0 && pixels2[k + 3] != 0) {
                res = true;
            }
            if (i < ifin) {
                i = i + 1;
                i2 = i2 + 1;
            }
            else {
                i2 = clamp(pixelsSize1.x - pixelsSize1.x*((pixelsPos2.x - pixelsPos1.x + pixelsSize1.x) / pixelsSize1.x), 0.0f, pixelsSize1.x);
                i = 0;
                j = j + 1;
                j2 = j2 + 1;
            }
        }
    }
    else if (pixelsPos1.x + pixelsSize1.x >= pixelsPos2.x && pixelsPos1.y + pixelsSize1.y >= pixelsPos2.y && pixelsPos1.x + pixelsSize1.x <= pixelsPos2.x + pixelsSize2.x && pixelsPos1.y + pixelsSize1.y <= pixelsPos2.y + pixelsSize2.y) {
        float jfin = clamp(pixelsSize1.y*((pixelsPos2.y - pixelsPos1.y + pixelsSize1.y) / pixelsSize1.y), 0.0f, pixelsSize1.y);
        float j = 0;
        float ifin = clamp(pixelsSize1.x*((pixelsPos2.x - pixelsPos1.x + pixelsSize1.x) / pixelsSize1.x), 0.0f, pixelsSize1.x);
        float i = 0;
        float i2 = clamp(pixelsSize1.x - pixelsSize1.x*((pixelsPos2.x - pixelsPos1.x + pixelsSize1.x) / pixelsSize1.x), 0.0f, pixelsSize1.x);
        float j2 = clamp(pixelsSize1.y - pixelsSize1.y*((pixelsPos2.y - pixelsPos1.y + pixelsSize1.y) / pixelsSize1.y), 0.0f, pixelsSize1.y);
        while (j<jfin-1) {
            int k = floor((pixelsSize2.x*j) + i) * 4 - 1;
            int k2 = floor((pixelsSize1.x*j2) + i2) * 4 - 1;
            if (pixels1[k2 + 3] != 0 && pixels2[k + 3] != 0) {
                res = true;
            }
            if (i < ifin) {
                i = i + 1;
                i2 = i2 + 1;
            }
            else {
                i2 = clamp(pixelsSize1.x - pixelsSize1.x*((pixelsPos2.x - pixelsPos1.x + pixelsSize1.x) / pixelsSize1.x), 0.0f, pixelsSize1.x);
                i = 0;
                j = j + 1;
                j2 = j2 + 1;
            }
        }
    }
return res;
}

1 Ответ

0 голосов
/ 30 ноября 2018

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

...