• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker [Solved] Rotate Around Point Other Than Origin

O

Orion31

Guest
Okay, so I have a character model with a separate head and body sprite. The sprites are the same size but the head sprite is transparent where the body would be and the body is transparent where the head would be. The reason for this is that I want the head to be able to rotate independently of the body (I want the character to occasionally turn his head to make him look natural). I also scale the character up as it gets closer to the bottom of the room to simulate distance to the camera. I have a script setting image x and y scale to 0.8 * (room_height - y) + 0.25 I set the origin of both sprites to where the bottom of the feet are/would be so that as the character is scaled, its feet remain in the same spot. It is very important that the feet remain in the same spot because a) when I place the character in the room, if it does not scale around its feet, I cannot predict where it is going to be (like if I place the character on a road, but then scale for depth, the character will not be on the road) and b) when the character is walking, it looks weird. However, when I rotate the head around the origin (which is set to where the feet are), it does not look like the head is turning, but instead that the head is orbiting around a point.
So my question is: can I rotate a sprite around a point that isn't the origin of the sprite?
 

obscene

Member
Not easily. But it would be very easy to just put the origin at the neck and then just position the head in the correct spot. You can measure how many pixels it is from the foot to where the neck would join. Then multiply that by your scale.
 

sinigrimi

Member
I see two options, either you draw a full-fledged sprite by frames, or you make an oHead object and fix its position in relation to the player in the step event, but in this case you will have to deal with code duplication (if you assume head collisions with other objects) .

if you want to rotate the sprite around itself (change the angle), write in the step event image_angle + = 1 (any number), in the opposite direction - = 1. Remember that the step event runs at room_speed / sec
 
O

Orion31

Guest
But it would be very easy to just put the origin at the neck and then just position the head in the correct spot. You can measure how many pixels it is from the foot to where the neck would join.
Yeah, so what tried to do before coming here was make the origin the center of the head (for both the head and body sprite), but I have the issue with the feet being in the wrong place. The sprite is 512 by 512, the the center of the head is at (256, 220), which is 292 from the feet y. Idk what I should add to the y to make it line up tho is it 292 * 0.8 * (room_height - y)?

I see two options, either you draw a full-fledged sprite by frames, or you make an oHead object and fix its position in relation to the player in the step event, but in this case you will have to deal with code duplication (if you assume head collisions with other objects) .

if you want to rotate the sprite around itself (change the angle), write in the step event image_angle + = 1 (any number), in the opposite direction - = 1. Remember that the step event runs at room_speed / sec
I was rotating it with a custom rotate variable and then using draw_sprite_ext and replacing image_angle with the rotation, since I have many variables that contribute to rotation (head rotation, rotation from the walking animation so the character like bobs around idk, etc). I dont rly want to manually animate it frame by frame, since im not going for a pixel art style, so everything looks pretty smooth, it would be a lot of frames to animate. Also, I want the head rotation to be kinda random, again to give it that lifelike effect. Currently, I draw spr_player and spr_player_head at the same x and y, since the sprites are both 512 by 512, just the head has lots of transparency at the bottom, where the body will go, and vice versa
 

sinigrimi

Member
Yeah, so what tried to do before coming here was make the origin the center of the head (for both the head and body sprite), but I have the issue with the feet being in the wrong place. The sprite is 512 by 512, the the center of the head is at (256, 220), which is 292 from the feet y. Idk what I should add to the y to make it line up tho is it 292 * 0.8 * (room_height - y)?
I don’t quite understand what you mean by the word “rotation”, but if you need random numbers in rotation, use irandom_range. If you want your head to swing over the character in a random direction x = oPlayer.x + irandom_range (-20, 20). If around your axis you can do the same with image_ange. You can also change the image_angle depending on the position "x" of the head, if image_angle = x-oplayer.x In other cases, you will have to consider the movement of the head and specify it exactly sequentially.
 
O

Orion31

Guest
No what I mean is that I already have a working rotation system where the head is rotated anywhere between 3 or 6 degrees in alternating directions. All of that works for me. The problem is that the origin point of my sprite is not the center of the head, so when I rotate the head by 3 degrees with image angle or however I'm doing it, it does not look like a tilt of the head but like you held down the stick end of a lollipop and turned the whole thing. The actual lollipop (not including the stick) would be the head. I need the stick for certain calculations, but for rotation, I don't want the stick. Does that make more sense?
 

sinigrimi

Member
No what I mean is that I already have a working rotation system where the head is rotated anywhere between 3 or 6 degrees in alternating directions. All of that works for me. The problem is that the origin point of my sprite is not the center of the head, so when I rotate the head by 3 degrees with image angle or however I'm doing it, it does not look like a tilt of the head but like you held down the stick end of a lollipop and turned the whole thing. The actual lollipop (not including the stick) would be the head. I need the stick for certain calculations, but for rotation, I don't want the stick. Does that make more sense?
You can get a screenshot? The difficulties of translation do not let me understand
 
O

Orion31

Guest
You can get a screenshot? The difficulties of translation do not let me understand
Sure, here is spr_player_head:
upload_2020-1-31_15-25-54.png
spr_player:
upload_2020-1-31_15-26-27.png
Now, I should mention, to fix the problem of the rotation, I set the origin to the middle of the head, so when scaling for depth, the middle of the head is kept constant.
Position in room before scaling for depth (obj_player's sprite is spr_player, spr_player_head is drawn in code):
upload_2020-1-31_15-27-8.png
What that turns into in game after running image_xscale = clamp(.8 * (y / room_height) - .25, 0.05, 1)
upload_2020-1-31_15-28-49.png
They are modeled after south park since I cannot for the life of me draw pixel art so I'm going with simple geometric shapes and needed a reference point lmao
 

Attachments

O

Orion31

Guest
With a rotated head, he looks like this (working as intended, the head pivots around the center of the head, like he is tilting it):
upload_2020-1-31_15-31-33.png
Here is the rotated head when the origin is set to the feet (bottom center):
Here depth scaling keeps the feet in the correct position, solving one problem, but then the rotation issue becomes the other problem
upload_2020-1-31_15-33-28.png

Edit: here is what the position of the player in the room is after depth scaling with origin at feet. This is the correct position of the player. By depth scaling I mean image_scale = clamp(.8 * (y / room_height) - .25, 0.05, 1);
upload_2020-1-31_15-35-42.png
 

Attachments

sinigrimi

Member
With a rotated head, he looks like this (working as intended, the head pivots around the center of the head, like he is tilting it):
View attachment 28522
Here is the rotated head when the origin is set to the feet (bottom center):
Here depth scaling keeps the feet in the correct position, solving one problem, but then the rotation issue becomes the other problem
View attachment 28523

Edit: here is what the position of the player in the room is after depth scaling with origin at feet. This is the correct position of the player. By depth scaling I mean image_scale = clamp(.8 * (y / room_height) - .25, 0.05, 1);
View attachment 28525
when the center is on your feet, how do you indicate the position of the head x = oplayer.x, y = oplayer.y + the correct number? Does your screenshot with the wrong rotation look like you incorrectly pointed ohead.x, or shifted the center of the width of the trunk to the right? does ohead.image_scale scale with the same code as the body?
 
O

Orion31

Guest
when the center is on your feet, how do you indicate the position of the head x = oplayer.x, y = oplayer.y + the correct number? Does your screenshot with the wrong rotation look like you incorrectly pointed ohead.x, or shifted the center of the width of the trunk to the right? does ohead.image_scale scale with the same code as the body?
No matter the origin, they are both drawn at the same x and y which is obj_player's x and y. When the head is rotated when the origin is at the feet, the scale and position are the same, just the actual head moves to the right because of the origin point (it's like holding a hula hoop and spinning in a circle vs standing in the middle of a hula hoop and spinning it like that. I want the latter) There is no object for the head, but it is drawn in obj_players draw event as a sprite with the same rotation, position, and scale as the body.
 
O

Orion31

Guest
I wrote a post on the matter of rotating points https://yal.cc/2d-pivot-points/
Thank you! that was a lifesaver! Unfortunately, I don't know trig, so what should I set as my offset? Is it 292 since the foot origin is 292 pixels below the point i want to rotate around?

Should it look something like this? (h rotate is the sum of all rotation effects on the head)
x + lengthdir_x(h_rotate, 292), y + lengthdir_y(h_rotate, 292)
or is this wrong since the origin point is only shifting down 292, not changing x values?
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
Thank you! that was a lifesaver! Unfortunately, I don't know trig, so what should I set as my offset? Is it 292 since the foot origin is 292 pixels below the point i want to rotate around?

Should it look something like this? (h rotate is the sum of all rotation effects on the head)
x + lengthdir_x(h_rotate, 292), y + lengthdir_y(h_rotate, 292)
or is this wrong since the origin point is only shifting down 292, not changing x values?
You might want to inspect the post and the function arguments a little more closely.

Though for basics, you might very well get away with having the head as a separate sprite with centered origin and then drawing it relative to the body (at x,y-292*scale, for example)
 
O

Orion31

Guest
You might want to inspect the post and the function arguments a little more closely.

Though for basics, you might very well get away with having the head as a separate sprite with centered origin and then drawing it relative to the body (at x,y-292*scale, for example)
The 292*scale works well, but I forgot to mention that the entire body rotates as a unit when walking, so in that case I would want the head to rotate from the feet.
I reread your article, and I understand that the lines connect to the result of lengthdir_x and y, but I'm too stupid to connect the dots on how to implement that to figure out how much to shift the head over to negate the shifting from the rotation (or is that not what I am trying to do)

I tried this:
var headx = x + lengthdir_x(image_xscale * -292, h_rotate);
var heady = y + lengthdir_y(image_xscale * -292, h_rotate);
(h_rotate is the sum of rotations applied to the head)
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
The 292*scale works well, but I forgot to mention that the entire body rotates as a unit when walking, so in that case I would want the head to rotate from the feet.
I reread your article, and I understand that the lines connect to the result of lengthdir_x and y, but I'm too stupid to connect the dots on how to implement that to figure out how much to shift the head over to negate the shifting from the rotation (or is that not what I am trying to do)

I tried this:
var headx = x + lengthdir_x(image_xscale * -292, h_rotate);
var heady = y + lengthdir_y(image_xscale * -292, h_rotate);
(h_rotate is the sum of rotations applied to the head)
For that you would want to use the offset between the head's origin and body's rotation origin. Provided that body's origin is somewhere at the middle, your formula might prove to be correct. Drawing lines in your example for visualization might be worthwhile to figure out what is what
 
O

Orion31

Guest
For that you would want to use the offset between the head's origin and body's rotation origin. Provided that body's origin is somewhere at the middle, your formula might prove to be correct. Drawing lines in your example for visualization might be worthwhile to figure out what is what
The body rotation point is (256, 512), so bottom center, but the head rotation point is (256, 220), so 292 pixels up. The code I used above didn't work. If I I read your article correctly, when I do x + lengthdir_x(image_xscale * -292, h_rotate), I am getting the like from the body rotation center to the center of the head after it's been rotated, so the hypotenuse of the triangle. If I am correct, I can square that, subtract 292 squared and then I'll have the amount the head move to the left squared.
 

obscene

Member
You don't need lengthdir functions if the player's body isn't rotating. This should be easy as....

draw_sprite_ext(spr_body,x,y,etc...
draw_sprite_ext(spr_head,x,y-some_value,etc...)

If you are scaling it, it only gets slightly more complicated...

draw_sprite_ext(spr_body,x,y,etc...
draw_sprite_ext(spr_head,x,y-some_value*some_scale,etc...)
 
Last edited:
O

Orion31

Guest
You don't need lengthdir functions if the player's body isn't rotating. This should be easy as....

draw_sprite_ext(spr_body,x,y,etc...
draw_sprite_ext(spr_head,x,y-some_value,etc...)

If you are scaling it, it only gets slightly more complicated...

draw_sprite_ext(spr_body,x,y,etc...
draw_sprite_ext(spr_head,x,y-some_value*some_scale,etc...)
The problem is that I had to move the origin to the feet because I need the body to wobble when walking and the head needs to look like it's rotating with the body as one unit.

However, I also need the head to rotate around its center (or at least look like it does)

I made this in photoshop:
I sometimes need the head to act like the green circle, but sometimes need the transparent yellow.
Untitled-2.png
 
O

Orion31

Guest
I think I figured it out:

var headx = x + lengthdir_x(-292 * image_xscale, head_rotate + 90);
var heady = y - ((292 * image_xscale) - lengthdir_y(-292 * image_xscale, head_rotate + 90));

It looks perfect to me, but correct me if I am wrong.

Thank you obscene, YellowAfterlife, and sinigrimi
 
Top