bbox versus sprite_xoffset for boundary restraints?

J.T.

Member
Hello! I'm going through the "Breakthrough" tutorial and was just wondering why one code worked and one doesn't . . . This is concerning the part where the bat must be coded to stay within the boundaries of the game. This is the correct code in a Step event:

if keyboard_check(vk_right)
// Check for the right arrow key being held down
{
// This check is to make sure the bat doesn't go out of
// the room to the right
if x < room_width - sprite_xoffset - spd
{
x += spd;
}
else
{
x = room_width - sprite_xoffset;
}
}

But I'm wondering why this wouldn't work as well:

if keyboard_check(vk_right)
// Check for the right arrow key being held down
{
// This check is to make sure the bat doesn't go out of
// the room to the right
if x < bbox_right
{
x += spd;
}
else
{
x = room_width - sprite_xoffset;
}
}

When I use the second option the object continues to go off screen, but when I use bbox (in an intersect boundary event) to contain the ball within the game screen there is no problem:

if bbox_top < 0
{
// Reverse the vertical component of the speed vector
vspeed *= -1
}

Can someone explain the logic of this to me? Thank you!
 
Last edited:

TsukaYuriko

🌠
Forum Staff
Moderator
The bbox* variables contain the coordinates of the outer boundaries of an instance's bounding box. They change according to the instance's position in the room and the settings of its assigned mask.

x will therefore pretty much always be less than bbox_right (unless you have no mask assigned).

In comparison, if (bbox_top < 0) compares whether the top of the instance's bounding box is intersecting, or has left, the room's upper boundary (0).

The correct expression you're looking for would be if (bbox_right < room_width) - or, in other words, if the right boundary of the instance's bounding box is to the left of the room's right boundary.
 

TheouAegis

Member
Which technically is what you want -- comparing bbox_ coordinates to the boundary, not the offsets. The code you're learning from erroneous assumes your sprite will use a full bounding box. Most sprites do not use full bounding boxes, so by relying on the offsets, you risk stopping many pixels away from the boundary.
 

J.T.

Member
The bbox* variables contain the coordinates of the outer boundaries of an instance's bounding box. They change according to the instance's position in the room and the settings of its assigned mask.

x will therefore pretty much always be less than bbox_right (unless you have no mask assigned).

In comparison, if (bbox_top < 0) compares whether the top of the instance's bounding box is intersecting, or has left, the room's upper boundary (0).

The correct expression you're looking for would be if (bbox_right < room_width) - or, in other words, if the right boundary of the instance's bounding box is to the left of the room's right boundary.
Thank you so much! I cannot believe the answer was so simple... I have one more question though. The code that completely worked was:

if keyboard_check(vk_right){
if (bbox_right + spd < room_width)
{x += spd}}

When I didn't add spd, the bat went a little off screen and then snapped back into it, resulting in a "jiggle" motion. Why do I have to add the speed for it to work properly here but not when the ball bounces against the walls? As is:

if bbox_top < 0
{vspeed *= -1}
 

TsukaYuriko

🌠
Forum Staff
Moderator
Depending on the instance's mask (or more specifically, bounding box) and movement speed, it may be possible for the applied movement to "overshoot" the target position. If your movement speed is 4 and you're 3 pixels away from the border, you're technically not at the border yet - therefore movement will be applied, putting you 1 pixel past the border.

In order to avoid this, you would have to limit the range in which the instance can be located. You're already doing this in your code, but you're only doing so when the instance is already outside of the boundary - not right after you move it - so any overshoot as a result of this code will be in effect and visible until the next step.
 

J.T.

Member
Depending on the instance's mask (or more specifically, bounding box) and movement speed, it may be possible for the applied movement to "overshoot" the target position. If your movement speed is 4 and you're 3 pixels away from the border, you're technically not at the border yet - therefore movement will be applied, putting you 1 pixel past the border.

In order to avoid this, you would have to limit the range in which the instance can be located. You're already doing this in your code, but you're only doing so when the instance is already outside of the boundary - not right after you move it - so any overshoot as a result of this code will be in effect and visible until the next step.
Ah, I see. That makes total sense, thank you again for the explanation. But then why isn’t there any overshoot for the code in my intersect boundary step? :

If bbox_top < 0
{vspeed*= -1}

Sorry my questions are a little redundant!
 

TsukaYuriko

🌠
Forum Staff
Moderator
No amount of questions is redundant as long as you have a genuine interest in learning. ;)


The stars (or instances) may just have aligned properly to make exactly this case work "properly" - or at least to make it look like it does.

Probably what actually happens is that due to floating point precision (or lack thereof), your instance is ending up at Y coordinate -0.0001 or something, which, while not making the instance be drawn outside of the view, does count as less than 0 and will therefore cause it to turn around.

(Edit) Alternatively, maybe there's a row of transparent pixels at the top of your sprite, which might still be counted as a part of the bounding box. It could be all sorts of things - the only thing that's for sure is that it won't work under all circumstances.
 

J.T.

Member
No amount of questions is redundant as long as you have a genuine interest in learning. ;)


The stars (or instances) may just have aligned properly to make exactly this case work "properly" - or at least to make it look like it does.

Probably what actually happens is that due to floating point precision (or lack thereof), your instance is ending up at Y coordinate -0.0001 or something, which, while not making the instance be drawn outside of the view, does count as less than 0 and will therefore cause it to turn around.
Oh, makes perfect sense! You’re the best!!!! Thank you yet again!!!
 
Top