I want to do some rigidbody2D chains for characters(arms/legs etc.) and I would like to scale them to createan illusion of depth for a parallax effect. For example, imagine people walking around a town, some in the foreground, some in the background, but it’s not 3D, it’s still just 2D, as if you drew a picture that way.
The thing i can’t wrap my brain around, is that for a single character, I get exactly what I want if I just zoom the camera. Works perfectly, but when I want two or more characters on screen, possibly interacting it gets far more complicated. I want them to get smaller as they go in the -Y direction.
Scaling rigidbody2D’s and pinjoint2D’s seems to me like a matter of math, but I can’t figure it out. The normal Transform variables don’t mean anything it seems. How do I take a global position, scale it a bit to where it would be if it were bigger or smaller, while keeping all the inertia etc?
Really it doesn’t have to be a different size, I just want the character to look a different size.
I made some progress by switching to Rapier2D, but all I’ve managed so far is exploding body parts.
Well, no real depth/parallax can exist in 2d spaces, and changing shapes and joints positions while they are being pushed around by the physics engine would totally break its logic. One option I can think of is rendering to subviewport and then using the picture from that with a scale. Well it depends on how you intend to use the physics actuallly. You might just have invisible fixed size bodies and then copy the rotations from them to the scaled character sprites, with a RemoteTransform node or with code.
Then to create depth, you can literally just scale the root node based on their y-position. In a 2D game the bottom left corner of the screen is (0,0). So with a 1920 x 1600 screen size, -1600 is going to be the very top of the screen. You can do something like this:
#player.gd
func _physics_process(_delta: float) -> void:
# Get the current resolution of the screen.
# This is here so that it works regardless of the screen size
# the player chooses. Because you cannot control the
# resolution in full screen.
var screen_height = get_window().get_size().y
# Remember y is negative going up so we are going to get the
# difference. Doing this here will deal will our zero case
# and get us a 1.0 scale at the bottom of the screen.
var distance_from_screen = screen_height + global_position.y
# Multiply the fraction from 0.0 to 1.0 (top to bottom) that
# we are "away" from the screen and multiply it by a Vector
# equal to (1.0, 1.0) Then apply it to the scale.
scale = Vector2.ONE * (distance_from_screen / screen_height)
gravity = get_gravity()
move_and_slide()
If you wanted to make the player only half-sized at the top of the screen, you could replace the final line with: