[SOLVED] Is there a problem with image_xscale?

R

Robzoid

Guest
I'm working on slopes and they're very sensitive to collision mask changes. I'm getting stuck in the slope when my player object turns around (i.e. when its image_xscale value goes from 1 to -1). I determined that the collision mask is shifting by 1 pixel when the sprite flips but it's not apparent why since the sprite origin is perfectly centered.

This is the sprite. For testing purposes, this is the only sprite I'm using in gameplay. I made sure to make the image width an odd number (41) so that the origin can be precisely in the middle (20). The origin (20) is 20 pixels from the left bounding box (0) and 20 pixels from the right bounding box (40). It's square in the middle.

2019-04-20_16-32-07.png

I also commented out all my code in my step event except for the following:

2019-04-20_16-32-53.png

If I press enter, the image_xscale flips from 1 to -1 and vice versa. The show_debug_messages tell me the distance from the right edge of the collision mask to x and the distance from the left edge of the collision mask to x.

See the output of 20, -20 in the pic below. When he's facing right (i.e. image_xscale = 1), everything is as it should be. I would expect the output to remain the same when the image_xscale value flips to -1 but that's not what happens unfortunately.

2019-04-20_16-37-03.png

When I press Enter to flip, the output has switched to -21 and 19. This is why I'm getting stuck in the slope when I turn around.

2019-04-20_16-37-26.png

The collision mask needs to have the same orientation to the origin when the sprite flips. Am I missing something or does image_xscale not work right?
 

Slyddar

Member
Don't flip the actual image_xscale. Assign the flip value to a variable, like "facing", and draw it with draw_sprite_ext instead. It just causes too many problems using image_xscale directly.
 
R

Robzoid

Guest
Thanks for the reply. So it seems that image_xscale doesn't work as it should, which is disappointing. I wonder if I should create a thread in the tech support category. Also, you mention using draw_sprite_ext. This requires the draw event. According to https://docs2.yoyogames.com/source/_build/2_interface/1_editors/events/draw_events.html , "The draw event is a very intensive event, in that it's one of the events that takes up most time and resources." Do you know if using draw_sprite_ext in the draw event rather than using image_xscale in the step event would cause a performance hit?
 
D

Danei

Guest
I don't think I'd say it doesn't work as it should, it just doesn't have behavior that is conducive to this particular goal. The default behavior for the image_xscale variable would be helpful in some circumstances, if you do want the bounding box flipped along with the visible image.

As for the draw event, there is absolutely nothing wrong with using it for its intended purpose, i.e. drawing things. In many cases you can prepare the data that you want to draw in the step event to reduce the number of calculations performed in the draw event, but even that is rarely necessary unless you are actually seeing performance problems.
 

Slyddar

Member
"The draw event is a very intensive event, in that it's one of the events that takes up most time and resources." Do you know if using draw_sprite_ext in the draw event rather than using image_xscale in the step event would cause a performance hit?
Every instance in your game performs a draw event every step. It is hidden from you, but they all have a draw event with draw_self() as the default function. Adding a draw_sprite_ext will add absolutely no extra performance hit on your game, as it will consume the same cycles as a draw_self would do.
 

TheouAegis

Member
Has bounding box is an odd with. Because his Sprite is an odd width. If he changed his right bounds from 40 to 39 or from 40 to 41, then it would have worked just fine. it's just a common rookie mistake of somebody making an odd width sprite with an odd width bounding box thinking you need odd widths in order to have it centered. Or maybe he didn't do it intentionally and it just coincidentally turned out that way.
 
First thing I noticed was what TheouAegis pointed out, change the width of the sprite to an even number (probably just increase it's size by 1 pixel) and it should work fine without doing anything else.
 
R

Robzoid

Guest
Has bounding box is an odd with. Because his Sprite is an odd width. If he changed his right bounds from 40 to 39 or from 40 to 41, then it would have worked just fine. it's just a common rookie mistake of somebody making an odd width sprite with an odd width bounding box thinking you need odd widths in order to have it centered. Or maybe he didn't do it intentionally and it just coincidentally turned out that way.
First thing I noticed was what TheouAegis pointed out, change the width of the sprite to an even number (probably just increase it's size by 1 pixel) and it should work fine without doing anything else.
I'm not sure what you both mean. Are you saying that both the sprite width and the collision box width should be even or the sprite width odd and collision box width even? Or maybe the sprite width doesn't matter and the collision box width should be even? I made them both odd because that's the only way you can have a middle value. With an even width, let's say 4, there's no middle integer. 1 2 3 4. <--- no middle value. If the width is 5, then the middle value is 3. The middle value can serve like an axis while the rest rotates (from 1 2 3 4 5 to 5 4 3 2 1). That was my reasoning anyway.
 

TheouAegis

Member
The way it needs to be is the left bound of the Sprite itself needs to be either odd or even and the right bound needs to be either even or odd. So if your left bound is even, your right bound must be odd. If your left bound is odd, then you're right bound must be even. Fish crate dimensions itself don't really matter, but people tend to use automatic bounding box calculation settings, so a Sprite with a sprite with an odd width is going to have a bounding box with an odd wdth.

You're forgetting something important - the origin of a Sprite is relative to the pixels in that Sprite. If you have a a Sprite with only one pixel, an odd width, where is the origin going to be? Not in the middle of that pixel, but next to it. As a result, that pixel is going to move about the origin when you flip the Sprite. now, if you had a Sprite that was just two pixels side-by-side, you can center the origin and it will be directly in the middle of those two pixels. so when you flip the Sprite, the left pixel will be on the right and the right pixel will be on the left.
 
R

Robzoid

Guest
Thanks for the reply.

if you had a Sprite that was just two pixels side-by-side, you can center the origin and it will be directly in the middle of those two pixels. so when you flip the Sprite, the left pixel will be on the right and the right pixel will be on the left.
It seems like you're saying the origin is a point that exists between pixels (see "A" in pic below). To my understanding the origin is itself a pixel. It defines the x and y positions. See"B" in pic below.

Origin.png

From what I can tell, it appears the origin is a pixel and can't be between two pixels in a two-pixel-wide sprite. Please let me know if I'm wrong on this.

pixel3.png

pixel4.png

Also, thanks to everyone who replied. Changing the collision mask width to an even number did fix the issue of getting stuck in the slope. Using draw_sprite_ext also fixes the problem.
 

TheouAegis

Member
The origin is a point. You cannot see a point, so gm draws a crosshair below-right of that point. It's still a point, though. It's like, just because people usually show Jesus as a white man doesn't mean he was white; it's just easier to visualize.
 
R

Robzoid

Guest
Thanks. I can see how the origin existing as a point between pixels would be hard to represent.
 
I actually prefer how GMS1 represented it. And I have even submitted a feature request for GMS2 to visualize it more like it was visualized in GMS1.

Regardless, here's a little bit of extra visualization.


Both have "centered" origins. Obviously, one rotates more "correctly" around the center than the other.
 
Top