Godot Version
v4.4.1.stable.flathub [49a5bc7b6]
Question
Hi,
The position of my character hairs got an offset from the character itself. I don’t understand why as I’m using global_position to set the hair position.
Moreover, the closer the character is to (0, 0) the little the offset will be.
Here’s the code to set the position of the hairs.
for i in range(len(hairPoints)-1, -1, -1):
if i == 0:
hairPoints[i][0] = hairGenerator.global_position
Is the hair a child of the character’s node? If so, you probably just want to set its position
to 0, 0
; the position
of a child node is the sum of its position
and that of all its ancestors in the node hierarchy.
1 Like
I tried it but if I do so, the wiggle effect disappear. I may create a dedicated node for the hairs ?
It seems like what you want is something like:
Character
Hair
Hair
Hair
Where each is the child of the one above, and each has an offset of a few pixels in the appropriate dimension of their position
.
The hairs are not directly children of the character as they drawn with the _draw function.Tthe main hair point (the biggest circle) position is based on the hairGenerator node position, and the other hairs position depend on the main hair position, and here’s my tree:
@onready var hairGenerator: Node2D = $HairGenerator
# ARRAY
#[(pos_x, pos_y), (offset_x, offset_y), max_dist, radius]
var hairPoints: Array = [
[Vector2(0, 0), Vector2(0, 0), 0, 10],
[Vector2(0, 0), Vector2(-2, 3), 4, 8],
[Vector2(0, 0), Vector2(-1, 3), 3.5, 7]
]
func _draw() -> void:
if sprite.visible:
for p in hairPoints:
print(p[0], hairGenerator.global_position)
draw_circle(p[0], p[3], Color.PURPLE)
draw_circle(p[0], p[3], Color.BLACK, false)
func _physics_process(delta: float) -> void:
for i in range(len(hairPoints)-1, -1, -1):
if i == 0:
hairPoints[i][0] = hairGenerator.global_position
else:
hairPoints[i][0] = hairPoints[i][1]+hairPoints[i-1][0]
for i in range(len(hairPoints)):
if i != 0 && hairPoints[i][0].distance_to(hairPoints[i][1]+hairPoints[i-1][0]) > hairPoints[i][2]:
var dir = (hairPoints[i-1][0]+hairPoints[i][1]).direction_to(hairPoints[i][0])
var offset = dir*hairPoints[i][2]
hairPoints[i][0] = hairPoints[i-1][0]+offset+hairPoints[i][1]
queue_redraw()
You might find this simpler if you make your hair points out of Sprite2D
.
It’s weird because I followed a tutorial and it was working find in the video:
What sets the position of HairGenerator
?
I set it with the 2d editor (the highlighted point):
It looks to me like what’s happening is when you set the position of the first point from the global_position
of the hair node, all your offsets are blowing up. It’s a little hard to read with the array-of-arrays thing you have going there, but I think the reverse order offset calculation may be at fault.
1 Like
Sooooo, I may changed something in total despair and it works. I love programming 
func _draw() -> void:
if sprite.visible:
for i in range(len(hairPoints)):
if i==0:
draw_circle(hairGenerator.global_position-VAR.player.global_position, hairPoints[i][3], Color.PURPLE)
draw_circle(hairGenerator.global_position-VAR.player.global_position, hairPoints[i][3], Color.BLACK, false)
else:
draw_circle(hairPoints[i][0]-VAR.player.global_position, hairPoints[i][3], Color.PURPLE)
draw_circle(hairPoints[i][0]-VAR.player.global_position, hairPoints[i][3], Color.BLACK, false)
Thanks for your help
You’ve certainly changed a few things from this tutorial, including a major version upgrade. Regardless you should be able to use local coordinates to draw in a chain.
func _physics_process(delta: float) -> void:
for i in range(len(hairPoints)-1, -1, -1):
if i == 0:
hairPoints[i][0] = Vector2.ZERO
else:
hairPoints[i][0] = hairPoints[i][1]+hairPoints[i-1][0]
This code will have the effect of making the distance between each hair constant, I’ll stick with what I’ve found.
Thanks for helping me!