GML [SOLVED] Lengthdir Problem - Elements not moving properly in circle. X and Y don't match Sprite Origin.

Qlak

Member
Hello!

I'm having trouble with (probably) lengthdir. I spent so much time on it, but I just can't figure out what I am doing wrong.
I thought that maybe someone can give me the reason this is happening.

Basically I was trying to draw circles in front of the character, as hands and I used lengthdir x and y and image_angle to place them in the right place and so they turn with character.
It works, but for some reason they move slightly and its a bit annoying. When I look up, they are a little closer to the character, than when I look right or down. They also tend to move a little to the side:

Normal placement:

lengthdir1.png

GML:
var rightHandX = x + lengthdir_x(14, controllerAngle + 45);
var rightHandY = y + lengthdir_y(14, controllerAngle + 45);
var leftHandX = x + lengthdir_x(14, controllerAngle - 45);
var leftHandY = y + lengthdir_y(14, controllerAngle - 45);
And with circles moved to the middle:

lengthdir2.png

GML:
var rightHandX = x + lengthdir_x(14, controllerAngle);
var rightHandY = y + lengthdir_y(14, controllerAngle);
var leftHandX = x + lengthdir_x(22, controllerAngle);
var leftHandY = y + lengthdir_y(22, controllerAngle);

Some more info:
  • The controllerAngle variable is basically image_angle. So it works the same.
  • It is done in the draw event.
  • The sprite origin is set to middle center.
  • Tried changing circle size and also had this problem.
  • (added after reply) The character is properly centered in the sprite with equal number of pixels to the sides.
  • (added after reply) Original sprite is 129x129 so I have a "center pixel" for top-down game, and aiming convinience, but I checked for 128x128 as well and it did not work as well.
  • (added after reply) Seems like x and y of the character do not match sprite origin for some reason. Can be seen on screenshots with added red lines from the x and y position, further in this topic.
  • (added after reply) The little red dot on Character's Head is not made by GMS - it is drawn on Character Template Sprite to see the center of the character.


I ran out of ideas how to fix this, and it should be really simple... Just like target and aiming system in other games, it shouldn't move it should go around and move with character sprite.
Do you guys have any idea what could be the reason behind this?

Thanks in advance :)
Cheers!
 
Last edited:

Mk.2

Member
You mentioned that the sprite origin is set to middle center, but are you certain that the character is properly centered in the sprite? Measure the distance from all sides of the character to the edges of the sprite.
 

Qlak

Member
You mentioned that the sprite origin is set to middle center, but are you certain that the character is properly centered in the sprite? Measure the distance from all sides of the character to the edges of the sprite.
Sadly everything is fine with sprite. I checked what you said and it is ok. But just to be supersure I did import the template that I made for characters, which is aligned pixel-perfect, but it has the same symptoms :(. Hands move to the side and away or closer to the character, depending on the angle.

Przechwytywanie111.PNG
(character in upper screenshot has his hands further from body, than the one from the lower picture)
 

chamaeleon

Member
Sadly everything is fine with sprite. I checked what you said and it is ok. But just to be supersure I did import the template that I made for characters, which is aligned pixel-perfect, but it has the same symptoms :(. Hands move to the side and away or closer to the character, depending on the angle.

View attachment 31110
(character in upper screenshot has his hands further from body, than the one from the lower picture)
Can you draw something using draw_line (like a plus symbol) or anything else to indicate where x,y is for the character in both cases?
 

Qlak

Member
Ok guys, I think we're on to something thanks to your replies! :)


Can you draw something using draw_line (like a plus symbol) or anything else to indicate where x,y is for the character in both cases?
There you go, I made 4 separate lines coming from x, y to 90, 180, 270 and 0 degrees:

lengthdir3.png

GML:
draw_line_color(x, y, x + lengthdir_x(30, image_angle), y + lengthdir_y(30, image_angle), c_red, c_red);
draw_line_color(x, y, x + lengthdir_x(30, image_angle + 90), y + lengthdir_y(30, image_angle + 90), c_red, c_red);
draw_line_color(x, y, x + lengthdir_x(30, image_angle + 180), y + lengthdir_y(30, image_angle + 180), c_red, c_red);
draw_line_color(x, y, x + lengthdir_x(30, image_angle + 270), y + lengthdir_y(30, image_angle + 270), c_red, c_red);
As we can see, the middle point goes right down and just like hands sometimes is bit further from center of the template.


It is possible. I did see it, but it wasn't stated that it was drawn separately, and not the location of origin in the sprite.
Sorry for not mentioning that: the little DOT is the centre of the Character Template, it is not coded in game, center which game sees is now marked on the picture above, where lines cross each other (x, y).


Make sure also everything is even-width. No 7x7 sprites or 15x31 sprites.
I think that you might have found the problem, but I need some clarification then, maybe I am not aware of something.
The sprite I made is indeed 129x129 and not 128x128, but I made it like this on purpose.
I knew I was going to make the game top-down and I wanted to have max precision, so I wanted the center to be exactly in the middle and to have 64 pixels on each side. I thought that if I make it even, then the centre will be moved just a little.

lengthdir4.png

So it loos like 64px + 1px (center) + 64px. I guess that might be the error then?
If so, then please tell me, why it is not the middle as it is supposed to be? And what happens in case the sprite is even? Where is the center then?
 
64/2 = 32
65/2 = 32.5

You can't have half a pixel. There either is a pixel, or there isn't, so when you make something that you want to have a specific center that can be rotated around smoothly, you have to use evenly divisible numbers. Think of the center pixel itself as a little circle that gets rotated. If you have any extra left over after dividing the whole width and height by half, then that "center pixel circle" will be offset from the true center by whatever the leftover is, meaning the rotational center of the sprite won't be the actual center of the sprite.
 

Nidoking

Member
I believe it's actually the other way around. You want to have odd dimensions so that the center is a pixel. Otherwise, the center of rotation is not the center of the sprite, and you get effects like what's shown here.

From the pictures, it looks like the origin of the sprite is off-center. Have you checked that? If that final screenshot is the entire sprite, then it appears that the size of the transparent part at the edge is also odd, so if you just hit "Center" for the origin, it might not be finding the right pixel. Try setting it manually.
 

Qlak

Member
Think of the center pixel itself as a little circle that gets rotated. If you have any extra left over after dividing the whole width and height by half, then that "center pixel circle" will be offset from the true center by whatever the leftover is, meaning the rotational center of the sprite won't be the actual center of the sprite.
I believe that this is the reason, but I still do not exactly get it. Why do we have to divide the pixels? This center-pixel was the exact reason why I made the sprite 129x129 :D. To have the center of character in the top-down game and be able to make aiming system without any problems. If I would like to make a 1px line from the centre of the character in 128x128 sprite, then I thought it would be a little on the left or right, but not center. This is the reason why I decided to have odd number.



I believe it's actually the other way around. You want to have odd dimensions so that the center is a pixel. Otherwise, the center of rotation is not the center of the sprite, and you get effects like what's shown here.

From the pictures, it looks like the origin of the sprite is off-center. Have you checked that? If that final screenshot is the entire sprite, then it appears that the size of the transparent part at the edge is also odd, so if you just hit "Center" for the origin, it might not be finding the right pixel. Try setting it manually.
Yes I did check origin so many times, besides when I click middle-center it finds perfect spot, since the sprite has that middle pixel (64px + 1px + 64px), in the program it is 64x64 (0-63, 64 - center pixel, 65-128). Have a look:

lengthdir5.png
 

Qlak

Member
Make sure also everything is even-width. No 7x7 sprites or 15x31 sprites.
64/2 = 32
65/2 = 32.5

You can't have half a pixel. There either is a pixel, or there isn't, so when you make something that you want to have a specific center that can be rotated around smoothly, you have to use evenly divisible numbers. Think of the center pixel itself as a little circle that gets rotated. If you have any extra left over after dividing the whole width and height by half, then that "center pixel circle" will be offset from the true center by whatever the leftover is, meaning the rotational center of the sprite won't be the actual center of the sprite.

Ok guys, sadly this was not the problem either.
I remade my sprite and made it 128x128 (of course I changed size of character by 1 pixel, centered everything properly and so on).
Started the game and the lines moved even further now. No idea why.

lengthdir6.png
 
I believe it's actually the other way around. You want to have odd dimensions so that the center is a pixel. Otherwise, the center of rotation is not the center of the sprite, and you get effects like what's shown here.

From the pictures, it looks like the origin of the sprite is off-center. Have you checked that? If that final screenshot is the entire sprite, then it appears that the size of the transparent part at the edge is also odd, so if you just hit "Center" for the origin, it might not be finding the right pixel. Try setting it manually.
You made me curious as to whether I was wrong, so I made two sprites, one 95x95 and the other 96x96 and tried some rotational work with them. Here's a gif I recorded, the one on the left is 95x95 and the one on the right is 96x96, it's a little hard to tell in the gif (but is obvious viewing in GMS), but the 95x95 sprite has a wobble when rotating around it's center. The 96x96 rotates completely smoothly. The red dots are just projections that show the pointing direction of each circle (and the stuff in the middle is where the point direction is coming from).


So yeah, odd sized sprites do not rotate correctly, it is as I said, you can't have a center position be "half" a pixel. If the sprite width does not divide evenly, the center position will not be in the true center of the sprite and there will be movement when rotating around it.

On topic edit: I would still guess that you're doing something wrong with the sprite size. Lengthdir has never had any errors for me and I'm super anal about stuff aligning properly, so I would've noticed if there was anything weird about it as I use it a lot for alignment of various things exactly as you are. Make sure that your sprite is centered properly within your image (this means transparent areas to the left and right of your sprite should both be the same size, as well as transparent areas on the top and bottom being the same size). Make sure you have your sprite origin correctly centered (origin x and origin y both need to be even numbers). If those red lines that you are drawing through the x and y don't actually align with the direct center of your sprite, you have SOMETHING misaligned.
 
Last edited:

chamaeleon

Member
It has not been completely spelled out (I think! I may have missed, and if so I'm sorry..), but the rotation point is in the location at the shared location of four pixels, so in-between. Here's an example of a 3x3 and 2x2 sprite to show it in detail: https://forum.yoyogames.com/index.p...a-problem-with-image_xscale.62248/post-374991
I think as far as the sprite editor is concerned the rotation point becomes the point at the top-left corner of the pixel that is the center of the cross.
 

Qlak

Member
So yeah, odd sized sprites do not rotate correctly, it is as I said, you can't have a center position be "half" a pixel. If the sprite width does not divide evenly, the center position will not be in the true center of the sprite and there will be movement when rotating around it.

On topic edit: I would still guess that you're doing something wrong with the sprite size. Lengthdir has never had any errors for me and I'm super anal about stuff aligning properly, so I would've noticed if there was anything weird about it as I use it a lot for alignment of various things exactly as you are. Make sure that your sprite is centered properly within your image (this means transparent areas to the left and right of your sprite should both be the same size, as well as transparent areas on the top and bottom being the same size). Make sure you have your sprite origin correctly centered (origin x and origin y both need to be even numbers). If those red lines that you are drawing through the x and y don't actually align with the direct center of your sprite, you have SOMETHING misaligned.

Yeah, but after reading your last response I did change the sprite to be 128x128 and cut it properly so it is properly centered:


probl1.gif



I imported this sprite to GMS and set Origin to Middle Center, then when I started the game I got the same results as earlier (like on the screenshot in previous reply):

probb4.gif


I really don't get it. In this case it works totally the same for 129x129 sprite and for 128x128 sprite. It is like the origin was in different place. I tried so many different things already and the result is always the same 😔
 

Qlak

Member
It has not been completely spelled out (I think! I may have missed, and if so I'm sorry..), but the rotation point is in the location at the shared location of four pixels, so in-between. Here's an example of a 3x3 and 2x2 sprite to show it in detail: https://forum.yoyogames.com/index.p...a-problem-with-image_xscale.62248/post-374991
I think as far as the sprite editor is concerned the rotation point becomes the point at the top-left corner of the pixel that is the center of the cross.
Thanks for sharing this, it makes sense for me now. I need to stick to even numbers for sure, so that is something. Now I only need to find why my Sprite behaves this way even on 128x128.
 

chamaeleon

Member
I really don't get it. In this case it works totally the same for 129x129 sprite and for 128x128 sprite. It is like the origin was in different place. I tried so many different things already and the result is always the same 😔
Do you have a custom draw event or are you using image_angle only to rotate the sprite? I'm just curious, because the rotating image shows clearly that the drawn crosshair has one rotation point, while the dot in the sprite has another, both static in location. That can't be true without a draw event that draws the sprite manually if the crosshair center point is at x,y, I think..

Edit: Unless it's some kind of artifact due to scaling up..
 

Qlak

Member
Please post your sprite at the normal scale.
Here it is, 128x128 sprite with image_scale 1. I also checked that and when I make hands bigger, they also tend to move a little (character facing down/right moves them further away; facing up/left closer).

fullscale.PNG
 

Qlak

Member
Do you have a custom draw event or are you using image_angle only to rotate the sprite? I'm just curious, because the rotating image shows clearly that the drawn crosshair has one rotation point, while the dot in the sprite has another, both static in location. That can't be true without a draw event that draws the sprite manually if the crosshair center point is at x,y, I think..

Edit: Unless it's some kind of artifact due to scaling up..

Yes I use custom draw event, so I can draw body, head, feet and arms over there.
The cross made from lines is made in code, as someone here requested earlier, while the little red circle in the middle is the center of the Template Character Sprite, to see where is the sprite center. It is drawn in aseprite.
 
So, I assume, you are scaling your view? Because that image is not 128x128. Can you post the original sprite you are using, not it as it appears in game with view/surface scaling applied? Also, that image is 713x777, which are both odd numbers, so if that is the size of the sprite in GMS, then it is most definitely -not- evenly sized.
 

chamaeleon

Member
Yes I use custom draw event, so I can draw body, head, feet and arms over there.
The cross made from lines is made in code, as someone here requested earlier, while the little red circle in the middle is the center of the Template Character Sprite, to see where is the sprite center. It is drawn in aseprite.
I should have realized you use a custom draw event because I asked for the lines... Anyway, I firmly believe your origin is not in the correct position and should be shifted up and to the left, perhaps one step. The origin point should be width/2 and height/2, so presumably 64,64 in the sprite editor, I think.
 

Qlak

Member
So, I assume, you are scaling your view? Because that image is not 128x128. Can you post the original sprite you are using, not it as it appears in game with view/surface scaling applied? Also, that image is 713x777, which are both odd numbers, so if that is the size of the sprite in GMS, then it is most definitely -not- evenly sized.
Sorry, I misunderstood. This is the ORIGINAL SPRITE (other was only a screenshot from the game, sorry for that).
Two original images, head and body, both 128x128 that I recreated today:
spr_template_body128.png spr_template_head128.png



And here are the old ones 129x129:
spr_template_body.png spr_template_head.png
 

Qlak

Member
I should have realized you use a custom draw event because I asked for the lines... Anyway, I firmly believe your origin is not in the correct position and should be shifted up and to the left, perhaps one step. The origin point should be width/2 and height/2, so presumably 64,64 in the sprite editor, I think.
You are correct it is 64x64 as it's supposed to be. After reading what you linked I also tried moving origin by one pixel up and left, just to make sure, but as they wrote, the little crosshair is being drawn one pixel below and to right to show where between the pixels the origin will be.

Przechwytywanie11111111111111111111.PNG

So origin seems to be set ok.
 

chamaeleon

Member
You are correct it is 64x64 as it's supposed to be. After reading what you linked I also tried moving origin by one pixel up and right, just to make sure, but as they wrote, the little crosshair is being drawn one pixel below and to right to show where between the pixels the origin will be.
So origin seems to be set ok.
For some reason I'm not sure if it's been asked or answered.. But are the "hand" sprites also evenly sized, with an origin at width/2 and height/2?
 

Qlak

Member
For some reason I'm not sure if it's been asked or answered.. But are the "hand" sprites also evenly sized, with an origin at width/2 and height/2?
There are no hand sprites. I wanted to use circles drawn by GMS. And when I made them I noticed that when I rotate the character, circles move slightly, while they should be at the same place, regarding the sprite, no matter the character direction.

As I posted earlier, hand placement:
GML:
var rightHandX = x + lengthdir_x(14, controllerAngle + 45);
var rightHandY = y + lengthdir_y(14, controllerAngle + 45);
var leftHandX = x + lengthdir_x(14, controllerAngle - 45);
var leftHandY = y + lengthdir_y(14, controllerAngle - 45);
And hand drawing:
GML:
scr_draw_circle_outline(rightHandX, rightHandY, 2, c_green, c_yellow, c_black, 1);
scr_draw_circle_outline(leftHandX, leftHandY, 2, c_white, c_red, c_black, 1);
I do not think hands are the problem here, the lines that you asked for earlier, also have this problem.
 

chamaeleon

Member
There are no hand sprites. I wanted to use circles drawn by GMS. And when I made them I noticed that when I rotate the character, circles move slightly, while they should be at the same place, regarding the sprite, no matter the character direction.

As I posted earlier, hand placement:
GML:
var rightHandX = x + lengthdir_x(14, controllerAngle + 45);
var rightHandY = y + lengthdir_y(14, controllerAngle + 45);
var leftHandX = x + lengthdir_x(14, controllerAngle - 45);
var leftHandY = y + lengthdir_y(14, controllerAngle - 45);
And hand drawing:
GML:
scr_draw_circle_outline(rightHandX, rightHandY, 2, c_green, c_yellow, c_black, 1);
scr_draw_circle_outline(leftHandX, leftHandY, 2, c_white, c_red, c_black, 1);
I do not think hands are the problem here, the lines that you asked for earlier, also have this problem.
You're using draw_circle() for the hands? Try using leftHandX-1, leftHandY-1, rightHandX-1, and rightHandY-1 as arguments for the respective hands. It may be an artifact of how graphics primitives are drawn contrasted to pixels in sprites.
 

Qlak

Member
You're using draw_circle() for the hands? Try using leftHandX-1, leftHandY-1, rightHandX-1, and rightHandY-1 as arguments for the respective hands. It may be an artifact of how graphics primitives are drawn contrasted to pixels in sprites.
Holy cow, mate you nailed it!
I added the same to the lines and now they're also in the center! Hands are not moving anymore.

probl3333333333.gif

I had no idea about something like this. Still not sure what are these artifacts.
Cheers man!

And thanks everyone who tried to help me with this thing. Can't believe that the fix was so simple. It took so many hours...

🍻
 

TheouAegis

Member
draw_circle() draws from the top-left, probably. You calculate hand position based on where you expect the centers to be, but instead it was probably where the top-left point would be.
 
Top