- Title: Bounding Box Offset Error Correction for Mirrored or Flipped Sprites
- Description: This script will return the correct bounding box values in the room for instances with mirrored or flipped sprites.
- GM Version: :GM81:
- Registered: No
- File Type: .gml (Use "Import Scripts..." to add to your game then rename to sprite_get_bbox)
- File Size: 3kb
- File Link: http://www.mediafire...1iysds8yc5m8ibi , http://sharesend.com/xj9pw
Game Maker has a nasty little bug when you mirror or flip sprites using the image_xscale or image_yscale variables. This isn't anything new and was even present on the Nintendo Entertainment System (don't worry if you're too young to know what that is). When you mirror or flip a sprite using these variables, the bounding box dimensions in the room -- as defined by the variables bbox_left, bbox_top, bbox_right, and bbox_bottom -- gets stretched and/or shifted. Why does it do this? My guess it is has to do with how bitwise negation works, but you don't need to concern yourself with that.
If you ever want to use any of these four variables with a mirrored or flipped sprite, you will need to compensate for the shift in values. I have taken the guesswork out of it and devised a script which will handle the values for you. You could just as easily set image_xscale and image_yscale to positive, retrieve the bounding box values, then set image_xscale and image_yscale back to where they were via a temporary variable, but this script is my preferred alternative.
Note that only negation affects the bounding box adversely; all negative scale values will yield incorrect bounding box values. Further scaling (setting to anything other than 1 or -1) does affect the bounding box, but there are no errors in the shift beyond what is already caused by using a negative value.
Remember, the argument is passed as a string.
//Corrects bounding box offsets in room when using negative sprite scaling
//Use: sprite_get_bbox(bbox)
if (argument=='bbox_left' || argument=='bbox_right')
{
var true_L,true_R;
//Store bounding box coordinates in the room for manipulation
true_L = bbox_left;
true_R = bbox_right;
if image_xscale<0
{
var diff_L,diff_R;
//Calculate distances bounding box edges are from sprite border
diff_L = sprite_get_bbox_left(sprite_index);
diff_R = sprite_get_width(sprite_index)-1-sprite_get_bbox_right(sprite_index);
//Check and compensate for symmetrical bounding box stretching
if diff_L = diff_R
{
true_L += 1;
true_R -= 1;
}
else
//Check and compensate for leftward stretch
if diff_L > diff_R
{
//Check and compensate for bounding box shift to the left
true_L += 1 + diff_L - diff_R;
true_R += diff_L - diff_R - 1;
}
else
//Check and compensate for rightward stretch
if diff_R > diff_L
{
//Check and compensate for bounding box shift to the right
true_L -= diff_R - diff_L - 1;
true_R -= diff_R - diff_L + 1;
}
}
//Return the corrected bbox_ value
switch argument
{
case "bbox_left": return true_L; exit;
case "bbox_right": return true_R; exit;
}
}
else
if (argument=='bbox_top' || argument='bbox_bottom')
{
var true_T,true_B;
//Store bounding box coordinates in the room for manipulation
true_T = bbox_top;
true_B = bbox_bottom;
if image_yscale<0
{
var diff_T,diff_B;
//Calculate distances bounding box edges are from sprite border
diff_T = sprite_get_bbox_top(sprite_index);
diff_B = sprite_get_height(sprite_index)-1-sprite_get_bbox_bottom(sprite_index);
//Check and compensate for symmetrical bounding box stretching
if diff_T = diff_B
{
true_T += 1;
true_B -= 1;
}
else
//Check and compensate for upward stretch
if diff_T > diff_B
{
//Check and compensate for bounding box shift up
true_T += 1 + diff_T - diff_B;
true_B += diff_T - diff_B - 1;
}
else
//Check and compensate for downward stretch
if diff_B > diff_T
{
//Check and compensate for bounding box shift down
true_T -= diff_B - diff_T - 1;
true_B -= diff_B - diff_T + 1;
}
}
//Return the corrected bbox_ value
switch argument
{
case 'bbox_top': return true_T; exit;
case 'bbox_bottom': return true_B; exit;
}
}
An alternative as proposed by icuurd12b42, setting new variables to use.
//Corrects bounding box offsets in room when using negative sprite scaling
//This version creates 4 variables to be used instead of the bbox_D family.
//Use: sprite_get_bboxes()
//Store bounding box coordinates in the room for manipulation
true_left = bbox_left;
true_right = bbox_right;
true_top = bbox_top;
true_bottom = bbox_bottom;
if image_xscale<0
{
var diff_L,diff_R;
//Calculate distances bounding box edges are from sprite border
diff_L = sprite_get_bbox_left(sprite_index);
diff_R = sprite_get_width(sprite_index)-1-sprite_get_bbox_right(sprite_index);
//Check and compensate for symmetrical bounding box stretching
if diff_L = diff_R
{
true_left += 1;
true_right -= 1;
}
else
//Check and compensate for leftward stretch
if diff_L > diff_R
{
//Check and compensate for bounding box shift to the left
true_left += 1 + diff_L - diff_R;
true_right += diff_L - diff_R - 1;
}
else
//Check and compensate for rightward stretch
if diff_R > diff_L
{
//Check and compensate for bounding box shift to the right
true_left -= diff_R - diff_L - 1;
true_right -= diff_R - diff_L + 1;
}
}
if image_yscale<0
{
var diff_T,diff_B;
//Calculate distances bounding box edges are from sprite border
diff_T = sprite_get_bbox_top(sprite_index);
diff_B = sprite_get_height(sprite_index)-1-sprite_get_bbox_bottom(sprite_index);
//Check and compensate for symmetrical bounding box stretching
if diff_T = diff_B
{
true_top += 1;
true_bottom -= 1;
}
else
//Check and compensate for upward stretch
if diff_T > diff_B
{
//Check and compensate for bounding box shift up
true_top += 1 + diff_T - diff_B;
true_bottom += diff_T - diff_B - 1;
}
else
//Check and compensate for downward stretch
if diff_B > diff_T
{
//Check and compensate for bounding box shift down
true_top -= diff_B - diff_T - 1;
true_bottom -= diff_B - diff_T + 1;
}
}
One more alternative, which should be called only when the sign of image_xscale or image_yscale is changed.
//Corrects bounding box offsets in room when using negative sprite scaling
//This version creates 4 variables you should add to each bbox_Dir reference.
//Ideally, only call this when the sign of image_xscale or image_yscale is changed.
//Use: sprite_get_bbox_offset()
//
//Example Usage: draw_rectangle(bbox_left+t_left,bbox_top+t_top,bbox_right+t_right,bbox_bottom+t_bot,0)
//Create the four new variables
t_left = 0;
t_right = 0;
t_top = 0;
t_bot = 0;
if image_xscale<0
{
var diff_L,diff_R;
//Calculate distances bounding box edges are from sprite border
diff_L = sprite_get_bbox_left(sprite_index);
diff_R = sprite_get_width(sprite_index)-1-sprite_get_bbox_right(sprite_index);
//Check and compensate for symmetrical bounding box stretching
if diff_L = diff_R
{
t_left += 1;
t_right -= 1;
}
else
//Check and compensate for leftward stretch
if diff_L > diff_R
{
//Check and compensate for bounding box shift to the left
t_left += 1 + diff_L - diff_R;
t_right += diff_L - diff_R - 1;
}
else
//Check and compensate for rightward stretch
if diff_R > diff_L
{
//Check and compensate for bounding box shift to the right
t_left -= diff_R - diff_L - 1;
t_right -= diff_R - diff_L + 1;
}
}
if image_yscale<0
{
var diff_T,diff_B;
//Calculate distances bounding box edges are from sprite border
diff_T = sprite_get_bbox_top(sprite_index);
diff_B = sprite_get_height(sprite_index)-1-sprite_get_bbox_bottom(sprite_index);
//Check and compensate for symmetrical bounding box stretching
if diff_T = diff_B
{
t_top += 1;
t_bot -= 1;
}
else
//Check and compensate for upward stretch
if diff_T > diff_B
{
//Check and compensate for bounding box shift up
t_top += 1 + diff_T - diff_B;
t_bot += diff_T - diff_B - 1;
}
else
//Check and compensate for downward stretch
if diff_B > diff_T
{
//Check and compensate for bounding box shift down
t_top -= diff_B - diff_T - 1;
t_bot -= diff_B - diff_T + 1;
}
}Edit Notes 04/09/12: Optimized code.
[i]Edit Notes 04/19/12: Added icuurd12b42 variant code[/b]
Edited by TheouAegis, 20 April 2012 - 05:02 AM.











