Why are the four diagonal directions in 8-way control so significantly offset?

Tested versions

v4.2.1.stable.official [b09f793f5]

System information

Window 11 v4.2.1.stable.official [b09f793f5]

Issue description

I implemented an 8-directional movement of a character controlled by the mouse using the program below. The up, down, left, and right movements work very well, but when moving in diagonal directions, the offset is very large. I can’t think of any solution to this problem. Could you please take a look and help?

func _physics_process(_delta):
	var player_position = position
	var mouse_position = get_local_mouse_position()
	# (0,1,2,3,4,5,6,7)
	var player_angle = wrapi(int(snapped(mouse_position.angle(), PI/4) / (PI/4)), 0, 8)
	var direction = Vector2(cos(player_angle * PI/4), sin(player_angle * PI/4))
	if player_action_speed > 0 and mouse_position.length() > 15:
		velocity = direction.normalized() * 100
		move_and_slide()

To demonstrate this issue, I have recorded a video.

I really need your help and guidance.

Steps to reproduce

My project source code is here: GitHub - aithority/engine: Tiance Engine based on Godot

Minimal reproduction project (MRP)

My project source code is here: GitHub - aithority/engine: Tiance Engine based on Godot

This is because your map’s tiles aren’t exactly at a 45-degree angle, but more like a 30-degree angle or so. You’ll need to fiddle around with the values so that diagonal movement follows the tiles’ rotation correctly.

1 Like

Because PI/4 corresponds to a 45º angle, but your isometric tiles are at a 30º angle if I’m not mistaken. I believe just changing PI/4 to PI/6 should suffice? I did not do the math, but =P

This is not quite right.

I tried again and placed a 45-degree tile in the map, which was indeed correct. However, if I want to move at a 30-degree angle, especially in the four corner directions, without changing the angle of the resources in the map, how should I handle it?

direction = Vector2(cos(PI/6), sin(PI/6)) would be your NE direction
direction = Vector2(cos(5 * PI/6), sin(5 * PI/6)) would be your NW direction
direction = Vector2(cos(7 * PI/6), sin(7 * PI/6)) would be your SW direction
direction = Vector2(cos(11 * PI/6), sin(11 * PI/6)) would be your SE direction

do with this information what you may

1 Like

Thank you for your help. I should have tried this calculation method before, and it probably didn’t solve the problem, but I will try again later.

This is (visually, at least) exactly the sort of thing that I’ll be trying to make with Godot, so I’ll be watching with interest. I wonder how much more annoying it would be to implement 16-direction movement rather than just 8. I bring this up only because I have downloaded some nice-looking free sprites that are animated in 16 directions.

I found a method where the built-in eight directions are only used to determine the player’s direction. The player’s walking position is located according to the tilemap grid. The tilemap grid coordinates are converted to world coordinates to control the player’s movement to the target location:

func update_target_position() -> void:
	var target_position = Vector2.ZERO
	var step = player_move_step
	var size = Global.get_map_grid_size()
	if player_angle == 0:
		target_position = Vector2(position.x + (step * size.x), position.y)
	if player_angle == 1:
		target_position = Vector2(position.x + (step * size.x), position.y + (step * size.y))
	if player_angle == 2:
		target_position = Vector2(position.x, position.y + (step * size.y))
	if player_angle == 3:
		target_position = Vector2(position.x - (step * size.x), position.y + (step * size.y))
	if player_angle == 4:
		target_position = Vector2(position.x - (step * size.x), position.y)
	if player_angle == 5:
		target_position = Vector2(position.x - (step * size.x), position.y - (step * size.y))
	if player_angle == 6:
		target_position = Vector2(position.x, position.y - (step * size.y))
	if player_angle == 7:
		target_position = Vector2(position.x + (step * size.x), position.y - (step * size.y))
	player_target_position = target_position
1 Like

You can use only 8 of the 16 directions in the resources.

1 Like

Thanks for the reply! This is very interesting. I wouldn’t have guessed that referencing the tilemap coordinates was the way to do this.