I need to create a function that returns a bool that is false if there is no collision between two sprites and true if there is, I was thinking for a long time and I can not find an exact solution, the objective is to detect if there is a collision per pixel, that is if two pixels with the alpha value (from rgba) different than 0 (it is visible) coincide in the same place in the space, the function has the following signature :
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 is a struct with the next form:
struct Vector2
{
float x;
float y;
};
pixelPos1 is the position of the upper left corner of the rectangle that contains sprite 1, pixelSize1 is the size (x = width; y = height) of the rectangle that contains sprite 1, pixel1 is a vector that has the rgba values of each pixel of the sprite, they are stored from 4 to 4 so that i contains the amount of r of the pixel i; i + 1 the amount of g of the pixel i; i + 2 the amount of b of the pixel i; i + 3 the amount of alpha of the pixel i, so that if i + 3 is different from 0 is a visible pixel, the size of pixel1 is given by pixelSize1.x * pixelSize1.y * 4. The other three parameters of the header are those corresponding to sprite 2. The objective would therefore be to check when there is a collision (either on the side or corner that is) and from there establish a collision rectangle between both rectangles (the coincident area), and set two indexes that travel pixel1 and pixel2 (since each one will have to start from a different position in its corresponding vector). The problem is that I can not find an optimal and / or easy way to do it and that it works. If anyone knows any way to do it, I would appreciate it very much.
EDIT Here is my code (it doesn't work)
#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;
}