how to apply sprite for 8 direction movement

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By potatobanana

i can apply animationplayer for 4 direction just fine but when come to 8 direction i have no idea, can someone help me, this my movement script for 8 direction.

var RIGHT = Input.is_action_pressed("ui_right")
var LEFT = Input.is_action_pressed("ui_left")
var DOWN = Input.is_action_pressed("ui_down")
var UP = Input.is_action_pressed("ui_up")
############Walking##################
move_direction.x = int(RIGHT) -int(LEFT)
move_direction.y = int(DOWN)  -int(UP)
 
:bust_in_silhouette: Reply From: Lucas Coelho

A faster but maybe not the best way to do this would be:

# Animation control handlers
if Input.is_action_pressed("ui_left") and !Input.is_action_pressed("ui_down") and !Input.is_action_pressed("ui_up"):
	_play_animation('w_l')
elif Input.is_action_pressed("ui_right") and !Input.is_action_pressed("ui_down") and !Input.is_action_pressed("ui_up"):
	_play_animation('w_r')

	
if Input.is_action_pressed("ui_up"):
	if Input.is_action_pressed("ui_left"):
		_play_animation('w_ul')

	elif Input.is_action_pressed("ui_right"):
		_play_animation('w_ur')

	else:
		_play_animation('w_u')


if Input.is_action_pressed("ui_down"):
	if Input.is_action_pressed("ui_left"):
		_play_animation('w_dl')

	elif Input.is_action_pressed("ui_right"):
		_play_animation('w_dr')

	else:
		_play_animation('w_d')

in this case _play_animation(name) is a function to change the current animation, but you don’t need to bother with this and you can change the Input.is_action_pressed(direction) for your respective direction variable.

Thanks for the answer, Lucas. I’ve been looking for a way to move my character in four or more directions while also changing the animation. This may prove useful.

Ertain | 2018-08-02 17:27

Notice that if you change the animation directly on _physics_process(delta) or even _process(delta) you need to prevent it from change if it’s already being played to avoid your animations of being stuck at the first frame. In my case, I have this _play_animation(name) like that:

_play_animation(animation_name):
    if old_animation != animation_name:
       $AnimationPlayer.play(animation_name)
       old_animation = animation_name

Lucas Coelho | 2018-08-02 17:30

Yeah, I’ve read some of GDQuest’s code, and Nathan’s put that if old_animation != animation_name: ... logic in his code.

Ertain | 2018-08-02 18:02

thank you you code easy to understand for beginer like me.

potatobanana | 2018-08-06 16:21

:bust_in_silhouette: Reply From: rk3Omega

You could store the animation paths to an array, then use the angle of move_direction to get the index to have your animation player play. And I added a facing value to store which direction you were last facing, otherwise it always turns right when idle.

var directions = ["right", "down_right", "down", "down_left", "left", "up_left", "up", "up_right"]
var facing = Vector2()

func _physics_process(delta):
	var move_direction = Vector2()
	
	var LEFT = Input.is_action_pressed("ui_left")
	var RIGHT = Input.is_action_pressed("ui_right")
	var UP = Input.is_action_pressed("ui_up")
	var DOWN = Input.is_action_pressed("ui_down")
	
	move_direction.x = int(RIGHT) - int(LEFT)
	move_direction.y = int(DOWN) - int(UP)
	
	if LEFT || RIGHT || UP || DOWN:
		facing = move_direction
	
	var animation = direction2str(facing)
	
	if $AnimationPlayer.assigned_animation != animation:
		$AnimationPlayer.play(animation)

func direction2str(direction):
	var angle = direction.angle()
	if angle < 0:
		angle += 2 * PI
	var index = round(angle / PI * 4)
	return directions[index]

thanks you for your teaching, i try out your code and it work, and it look simply elegant but i have no idea how PI work and make wonder how to apply idle/facing. because my old code switch between str(“idle”) and str(“move”) as you can see. my animation mostly loop.

for some reason when i paste my code here not all in gray

extends KinematicBody2D

const move_speed = 100
var move_direction = dir.center
var sprite_direction = "_Down"



func _physics_process(delta):
	control_loop()
	move_loop()
	sprite_loop()
	if move_direction != dir.center:
		animation_play("Fmove")
	else:
		animation_play("Fidle")
	
	
	pass

func control_loop():#control key
	var RIGHT = Input.is_action_pressed("ui_right")
	var LEFT = Input.is_action_pressed("ui_left")
	var DOWN = Input.is_action_pressed("ui_down")
	var UP = Input.is_action_pressed("ui_up")
	############Walking##################
	move_direction.x = int(RIGHT) -int(LEFT)
	move_direction.y = int(DOWN)  -int(UP)


func move_loop():
	var motion = move_direction.normalized() * move_speed
	move_and_slide(motion, dir.center)


func sprite_loop():
	match move_direction:
		dir.right:
			sprite_direction ="_Right"
		dir.left:
			sprite_direction = "_Left"
		dir.up:
			sprite_direction = "_Up"
		dir.down:
			sprite_direction = "_Down"


func animation_play(animation):# to atcive animation_switch
	var New_anim = str(animation,sprite_direction)
	if $anim.current_animation != New_anim:
		$anim.play(New_anim)

potatobanana | 2018-08-06 16:13

Howdy. Sorry just now seen you replied. I probably should’ve commented my code explaining it. Basically what the direction2str method does is get the angle you’re moving. It’s in radians, which is based on PI. So instead of -180 to 180 (degrees), it’s -PI to PI (3.14 etc). 0 is right, negative is counter-clockwise to right and positive is clockwise to right.

To make things simple we want to make angle positive, so if it’s less than 0, we add 2 * PI to it. So now angle is a value between 0 and 2 * PI. We can then divide it by PI * 4 and round it to get a value between 0 and 7, which correlates to the direction you’re facing. 0 being right going clockwise. You then use that value to determine which string in the array you need to use.

As for “idle” and “move”, I would have them named like “idle_right” and “move_right” etc. So that you can determine if you’re idling or moving, then do something along the lines of:

var suffix = "idle_"
var direction = direction2str(facing)
var animation = suffix + direction # idle_right

rk3Omega | 2018-08-24 14:19

I know I’m quite late to the party, but in my code I found some bugs where (angle / 4PI) was getting me 8, which is out of the bounds of the array. To solve this I returned

directions[int(index) % 8]

instead of just

directions[index]

in the direction2str function. This prevents any out-of-bounds by just making the index a ring of sorts.

wndr | 2020-07-15 08:56

:bust_in_silhouette: Reply From: sabacu

I have this difficulty, but in my project the movement is controlled by the mouse.
the code looks like this:

extends KinematicBody2D

export (int) var speed = 150

var target = Vector2()
var velocity = Vector2()
var ini_target = position

func _ready():
target = ini_target
pass

func _physics_process(_delta):

if Input.is_action_pressed("click"):
	target = get_global_mouse_position()

velocity = (target-position).normalized()*speed

if (target - position).length() > 5:
	velocity = move_and_slide(velocity)
	$sprite_move.play("mov_down")

else:
	$sprite_move.stop()

the code works well, but i have no idea how can i get the direction to the target to make a choose of wat animation the node plays.

This is not an answer to the original (two years old!) question. If you want to ask a related question, click the three dots in the bottom right corner and select “Ask Related Question”. That is in your interest, as it will appear as a new, unanswered question, thus people are a lot more likely to see it and help you.

i have no idea how can i get the direction to the target

You’re already using it: (target-position).normalized()

njamster | 2020-06-06 11:05