Homebrew NEED HELP WITH GRRLIB TRANSPARENCY COLLISION!!

  • Thread starter Thread starter FoxFore32x
  • Start date Start date
  • Views Views 637
  • Replies Replies 1

FoxFore32x

Member
Newcomer
Joined
Oct 10, 2019
Messages
16
Reaction score
0
Trophies
1
Age
20
XP
281
Country
Mexico
HOLD ON, I'VE PUT AN OBSOLETE CODE. I'VE UPDATED IT

i've been using GRRLIB for a while, and i figured out on how to make basic rectangular collision, and even managed to get it working with OriginX/Y, and left, right, top and bottom properties, so i can set where the collision starts specifically. However, something that i still couldn't figure out is pixel perfect / alpha based collision.

you see, i'm trying to implment it this way: i currently have 2 types of collision, which are "RECTANGLE" and "PRECISE" (one being the simple collision i've mentioned before and the other being the pixel perfect one). I want to make two conditions:

if ObjectA's Type = RECTANGLE && ObjectB's Type = PRECISE (or viceversa), and other being if both ObjectA's and B's Type = PRECISE.

I for the life of me couldn't get to implement this type of collision.

someone recomended me this tutorial, although idk if the library he's using handles pixels differently: Pixel Perfect Collision Detection in C

here's my code btw:

Sprite Handling:

C:
typedef struct {
    const unsigned char *spriteData;
    int spriteSize;
    int left;
    int right;
    int top;
    int bottom;
    int originX;
    int originY;
    int Type;
    CollisionMap Map;
} SpriteWithCollision;
extern SpriteWithCollision* currentSprite;

Object Handling;

C:
typedef struct {
    int id;
    float x;
    float y;
    float width;
    float height;
    int depth;
    SpriteWithCollision collision_mask;
    Layer layer;
    GRRLIB_texImg* texture;
    bool persistent;
    //struct GameList* parent;
    struct ObjectList* descendant; //User doesn't change it's value, it's the program who does the dirty work
} GameObject;
extern GameObject* currentObject; //Global Pointer to an array of GameObject pointers
typedef struct {
    GameObject* objects[MAX_OBJECTS];
    int numObjects;
    bool initialized;  // flag to track initialization status
} ObjectList;
typedef struct {
    ObjectList* Descen;
    ObjectList* Parent;
} ParObj;

My collision code, which has a messy logic for RECTANGLE && PRECISE Types:

C:
bool place_meeting(float x, float y, ObjectList *obj_list) {
    if (currentObject == NULL || obj_list == NULL) {
        return false; // No collision possible without valid input
    }
    SpriteWithCollision *currentSprite = &currentObject->collision_mask;
    // Calculate the current object's boundaries based on the given position
    float objLeft = x + currentSprite->left - currentSprite->originX;
    float objRight = x + currentObject->width + currentSprite->right - currentSprite->originX;
    float objTop = y + currentSprite->top - currentSprite->originY;
    float objBottom = y + currentObject->height + currentSprite->bottom - currentSprite->originY;
    // Iterate through the target object list
    for (int i = 0; i < obj_list->numObjects; ++i) {
        GameObject *otherObject = obj_list->objects[i];
        if (otherObject == NULL || otherObject == currentObject) {
            continue; // Skip null or self-collision
        }
        SpriteWithCollision *otherSprite = &otherObject->collision_mask;
        // Calculate the other object's boundaries
        float otherLeft = otherObject->x + otherSprite->left - otherSprite->originX;
        float otherRight = otherObject->x + otherObject->width + otherSprite->right - otherSprite->originX;
        float otherTop = otherObject->y + otherSprite->top - otherSprite->originY;
        float otherBottom = otherObject->y + otherObject->height + otherSprite->bottom - otherSprite->originY;
        bool isColliding = (objRight >= otherLeft && objLeft <= otherRight && objBottom >= otherTop && objTop <= otherBottom);
        // Handle collision types
        if (currentSprite->Type == RECTANGLE && otherSprite->Type == RECTANGLE) {
            if (isColliding){ return true; } // Simple bounding box collision
        }
        if ((currentSprite->Type == RECTANGLE && otherSprite->Type == PRECISE) ||
            (currentSprite->Type == PRECISE && otherSprite->Type == RECTANGLE)) {
            // Determine RECTANGLE and PRECISE objects
            SpriteWithCollision *rectSprite = (currentSprite->Type == RECTANGLE) ? currentSprite : otherSprite;
            SpriteWithCollision *preciseSprite = (currentSprite->Type == PRECISE) ? currentSprite : otherSprite;
            const GRRLIB_texImg *preciseTexture = (currentSprite->Type == PRECISE)
                                                    ? currentObject->texture
                                                    : otherObject->texture;
            // Determine positions for the PRECISE object
            float preciseX = (preciseSprite == currentSprite) ? currentObject->x : otherObject->x;
            float preciseY = (preciseSprite == currentSprite) ? currentObject->y : otherObject->y;
            // Calculate the scale factors for the PRECISE object
            float scaleX = (preciseSprite == currentSprite)
                            ? (currentObject->width / (preciseSprite->right - preciseSprite->left))
                            : (otherObject->width / (preciseSprite->right - preciseSprite->left));
            float scaleY = (preciseSprite == currentSprite)
                            ? (currentObject->height / (preciseSprite->bottom - preciseSprite->top))
                            : (otherObject->height / (preciseSprite->bottom - preciseSprite->top));
            // Calculate RECTANGLE bounds
            float rectLeft = (rectSprite == currentSprite) ? objLeft : otherLeft;
            float rectRight = (rectSprite == currentSprite) ? objRight : otherRight;
            float rectTop = (rectSprite == currentSprite) ? objTop : otherTop;
            float rectBottom = (rectSprite == currentSprite) ? objBottom : otherBottom;
            // Perform precise collision detection
            isColliding = CheckRectangleVsPrecise(
                rectLeft, rectTop, rectRight, rectBottom,
                preciseTexture, preciseSprite,
                preciseX, preciseY, scaleX, scaleY
            );
            if (isColliding) {
                return true;
            }
        }
        if (currentSprite->Type == PRECISE && otherSprite->Type == PRECISE) {
            if (isColliding){ return true; } // Simple bounding box collision
        }
        return false;
}

The function that's being used:

C:
bool CheckRectangleVsPrecise(float rectLeft, float rectTop, float rectRight, float rectBottom,
                              const GRRLIB_texImg *texture, const SpriteWithCollision *sprite,
                              float preciseX, float preciseY, float scaleX, float scaleY) {
    if (!texture || !sprite) {
        printf("Error: Invalid texture or sprite provided.\n");
        return false;
    }
    // Compute the scaled bounds of the precise sprite
    float preciseLeft = preciseX + (sprite->left - sprite->originX) * scaleX;
    float preciseRight = preciseLeft + (sprite->right - sprite->left) * scaleX;
    float preciseTop = preciseY + (sprite->top - sprite->originY) * scaleY;
    float preciseBottom = preciseTop + (sprite->bottom - sprite->top) * scaleY;
    // Early exit if there is no overlap
    if (rectRight < preciseLeft || rectLeft > preciseRight || rectBottom < preciseTop || rectTop > preciseBottom) {
        return false;
    }
    // Iterate over the overlapping region
    for (int y = MAX(rectTop, preciseTop); y < MIN(rectBottom, preciseBottom); ++y) {
        for (int x = MAX(rectLeft, preciseLeft); x < MIN(rectRight, preciseRight); ++x) {
            // Map world coordinates to the texture space
            int texX = (x - preciseLeft) / scaleX + sprite->left;
            int texY = (y - preciseTop) / scaleY + sprite->top;
            // Ensure the coordinates are within bounds
            if (texX < 0 || texX >= texture->w || texY < 0 || texY >= texture->h) {
                continue;
            }
            // Check if the pixel is non-transparent
            u32 pixelColor = GRRLIB_GetPixelFromtexImg(texX, texY, texture);
            if (A(pixelColor) > 0) {
                return true; // Collision detected
            }
        }
    }
    return false; // No collision found
}

Any help will be appreciated.
 
Last edited by FoxFore32x,
This is how I check if 2 squares over lap. I call this function and I pass the x,y, width and height of 2 squares and the function returns true or false. what you are doing up there is some kinda magic that you will have to debug yourself. its a whole lot of code and if you wrote it you probably should know why you wrote it that way instead of just comparing the player to every sprite in a single simple loop. if you cant figure it out I suggest you probably just avoid transparency entirely until you can debug the code.

Code:
player_pos=10,20;

foreach sprite do {
    if( aabb_2d(player_pos, sprit_pos, false)  ){
        //hit something. do this
        break;
    } else {
        //do that
    }
}


Code:
    bool aabb_2d(
                float x1, float y1,
                float x2, float y2,
                float w1, float h1,
                float w2, float h2,
                    bool show_debug ){

        aabb_check_counter++;

        temp_result=( aabb_overlap_internal(x1, x2, w1, w2) && aabb_overlap_internal(y1, y2, h1, h2)    );

        if(show_debug){
            draw_debug_box( x1,y1,w1,h1 );
            if(!temp_result) draw_debug_box( x2,y2,w2,h2 );
        }

        return temp_result;
    }
Post automatically merged:

texX, texY starts at the first pixel in the texture which is probably 1 then moves to the width/height of the pixel.

you need to ensure that you are passing the right values to this function;

GRRLIB_GetPixelFromtexImg(texX, texY, texture);

the only way to do this is to debug the code. the fastest way to do it is to print out the values on the screen using graphics (you could use text as well but it is most likely slower to read)
 
Last edited by newo,

Site & Scene News

Popular threads in this forum