在C ++中检测2D碰撞

时间:2018-11-30 19:39:12

标签: c++ multidimensional-array 2d collision-detection collision

我需要创建一个返回布尔值的函数,如果两个子画面之间没有碰撞,则返回false;如果存在,则返回true;我想了很长时间,但找不到确切的解决方案,目的是检测每个像素是否存在冲突,即如果两个alpha值(来自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是包含sprite 1的矩形的左上角的位置,pixelSize1是包含sprite 1的矩形的大小(x =宽度; y =高度),pixel1是具有rgba值的向量精灵每个像素的存储量为4到4,因此i包含像素i的r数量; i + 1像素i的g数量; i + 2像素i的b数量; i + 3像素i的alpha量,因此,如果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 :(得分:0)

首先检查两个精灵的边界矩形是否重叠。如果没有,那就太好了;没有碰撞是不可能的。如果它们确实重叠,则为每个子图计算重叠的矩形,并逐像素比较-如果像素a或像素b是透明的,则不会有该像素引起的碰撞,如果两个像素都不透明,则有碰撞,您可以完成。如果您完成了对重叠区域中所有像素的检查,并且没有冲突,那么操作也将完成。