As some of you may know, and as all of you [who use GameMaker] should know, image_xscale is bugged. I think the bug existed in the NES as well, but that's not important. What is important is that it is bugged. When image_xscale is negated, a method frequently used to mirror sprites, the sprite's bounding box gets changed. Actually, a lot of things get changed, but this important update simply concerns the bounding box. Using image_xscale=-1 (or image_xscale*=-1) increases the bounding box by 2px. I'd stated this before and it's been proven by others on the GMC forums. However, what hasn't been stated yet is that negating image_xscale also shifts the bounding box! It's a scary aspect you shouldn't neglect, but it is manageable:
Think of the bounding box in terms of two values - left_differential and right _differential. Simply put, left_differential is the value returned by sprite_get_bbox_left() and right_differential is the value returned by sprite_get_width()-sprite_get_bbox_right(). (Keep in mind that sprite_get_bbox_right() is not technically the same as bbox_right; the latter returns the x-value of bbox_right in the room, not how it relates to the rest of the sprite.) As long as left_differential and right_differential are equal, the bounding box increases by 2px evenly, subtracting 1 from bbox_left and adding 1 to bbox_right. However, this isn't the case when left_differential and right_differential are different.
One of two things can happen, depending on the values. If left_differential is 1 higher than right_differential, the bbox_left changes by 2 and bbox_right stays the same, and naturally vice-versa when right_differential is higher than left_differential. This is what happens when a sprite has a odd-valued sprite_width and full-image bounding box. However, if left_differential is 2 higher than right_differential, for example, the bounding box will actually shift to the left 1 pixel in addition to changing bbox_left by 2. If you thought that was bad enough, the shift increases depending on the difference between left_ and right_differential. If left_differential is 10 and right_differential is 2, the bounding box will shift 7 pixels and balloon out on the left side.
In summary:
left_differential += sprite_width mod 2
if left_differential != right_differential
{
if left_differential > right_differential
bbox_left -=2
else
bbox_right += 2
}
else
{
bbox_left -= 1
bbox_right += 1
}
bbox_left += (right_differential-left_differential)&!1
bbox_right += (right_differential-left_differential)&!1
where &! is something I made up meaning reduce the numerical value by 1
(e.g., -2 becomes -1, 3 becomes 2)