Hey guys, could anyone possibly figure out whats wrong with my sprite? (fixed! tysm for the help everyone)

Godot Version

4.6

Question

My player sprite broke when i replaced the placeholder with the actual sprite.

ive been using an online tutorial to help create a base for a 2d game, “Make a 2D Action & Adventure RPG in Godot 4” by Micheal Games on youtube. ive been using the free sprites he provides, and have decided to replace them with my own, starting with the player. it looks normal in the viewport, but when i playtest the game, it gets super pixelated and distorts when it moves, not slightly either, like it stretches across the screen and doesnt go back to normal
Animation

stuff like this keeps happening, this sprite was sized up and is shrinking, the sprite i want to use is resized to 0.1 and stretches back to its original x size

main player code

class_name Player extends CharacterBody2D

var cardinal_direction : Vector2 = Vector2.DOWN
var direction : Vector2 = Vector2.ZERO

@onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var sprite: Sprite2D = $Sprite2D
@onready var state_machine: PlayerStateMachine = $StateMachine

# Called when the node enters the scene tree for the first time.
func _ready():
	state_machine.Initialise(self)
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	
	##direction.x = Input.get_action_strength("right") - Input.get_action_strength("left")
	##direction.y = Input.get_action_strength("down") - Input.get_action_strength("up")
	direction = Vector2(
		Input.get_axis("left", "right"),
		Input.get_axis("up", "down"),
	).normalized()
	pass


func _physics_process( delta ):
	move_and_slide()

func SetDirection() -> bool:
	
	var new_dir : Vector2 = cardinal_direction
	if direction == Vector2.ZERO:
		return false
	
	if direction.y == 0:
		new_dir = Vector2.LEFT if direction.x < 0 else Vector2.RIGHT
	elif direction.x == 0:
		new_dir = Vector2.UP if direction.y < 0 else Vector2.DOWN
	
	if new_dir == cardinal_direction:
		return false
	
	cardinal_direction = new_dir
	sprite.scale.x = -1 if cardinal_direction == Vector2.LEFT else 1
	return true

func UpdateAnimation( state : String ) -> void:
	animation_player.play( state + "_" + AnimDirection() )
	pass

func AnimDirection() -> String:
	if cardinal_direction == Vector2.DOWN:
		return "down"
	elif cardinal_direction == Vector2.UP:
		return "up"
	else:
		return "side"

player state machine

class_name PlayerStateMachine extends Node

var states : Array[ State ]
var prev_state : State
var current_state : State

# Called when the node enters the scene tree for the first time.
func _ready():
	process_mode = Node.PROCESS_MODE_DISABLED
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(  delta ):
	ChangeState( current_state.Process( delta ) )
	pass

func _physics_process(  delta ):
	ChangeState( current_state.Physics( delta ) )
	pass

func _unhandled_input(event: InputEvent) -> void:
	ChangeState( current_state.HandleInput( event ) )
	pass

func Initialise( _player : Player ) -> void:
	states = []
	
	for c in get_children():
		if c is State:
			states.append(c)
	
	if states.size() > 0:
		states[0].player = _player
		ChangeState( states[0])
		process_mode = Node.PROCESS_MODE_INHERIT


func ChangeState( new_state : State ) -> void:
	if  new_state == null || new_state == current_state:
		return
	
	if current_state:
		current_state.Exit()
	
	prev_state = current_state
	current_state = new_state
	current_state.Enter() 

state_walk

class_name State_Walk extends State

@export var move_speed : float = 100.0

@onready var idle: State_Idle = $"../Idle"


##what happens when player enters state?
func Enter() -> void:
	player.UpdateAnimation("walk")
	pass

##what happens when player exits state?
func Exit() -> void:
	pass

##what happens during _process update in this state?
func Process( _delta : float ) -> State:
	if player.direction == Vector2.ZERO:
		return idle
	
	player.velocity = player.direction * move_speed
	
	if player.SetDirection():
		player.UpdateAnimation("walk")
	
	return null

##what happens during the _physics_process update in this state?
func Physics( _delta : float ) -> State:
	return null

##what happens with input events in this state?
func HandleInput( _event: InputEvent ) -> State:
	return null

state_idle

class_name State_Idle extends State

@onready var walk: Node = $"../Walk"

##what happens when player enters state?
func Enter() -> void:
	player.UpdateAnimation("idle")
	pass

##what happens when player exits state?
func Exit() -> void:
	pass

##what happens during _process update in this state?
func Process( _delta : float ) -> State:
	if player.direction != Vector2.ZERO:
		return walk
	player.velocity = Vector2.ZERO
	return null

##what happens during the _physics_process update in this state?
func Physics( _delta : float ) -> State:
	return null

##what happens with input events in this state?
func HandleInput( _event: InputEvent ) -> State:
	return null

im not sure what exactly to give yalls to mkaeit easier to figure out, so i thought to show everythin, none of the code is mine as stated, its all word for word from the tutorial i mentioned
for the record, the entire thing worked perfectly fine on the example sprite sheet attached to the tutorial.

i think its really important to mention i am an absolute noob at coding, so if anyones got any solution ideas, could you explain them in as much detail as possible? such as where to approximately insert a line of code, for example. :folded_hands:

1 Like

Show us.

You can record a video of what is happening, and /or add some screenshots of the Scene Tree with the nodes, a screenshot of the inspector tab with the individual details, and perhaps some code snippets of the movement being handled.

That way we can look at the exact details and give feedback - there is likely no one easy answer to any question like this one, but depends on an incorrect setting or organization issue

1 Like

Ay. What are your import settings of your actual sprite?

1 Like

heres the import settings of the sprite sheet, its a borrowed base off itch.io

1 Like

i added the code i have attached to the player. it includes the movement mechanics and the state machine the tutorial showed how to use.

1 Like

The set direction function changes the x scale to 1 or -1. What is the scale of the sprite in the character scene? I’m guessing the sprite is scaled to a bigger size in the scene, maybe something like (2, 2). When the function sets the x scale to 1 or -1, it becomes (1, 2) or (-1, 2) or something like that. So the character becomes skinny.

If that is indeed the issue, create an on ready var like default_scale_x that gets the initial x scale of the character on ready. Then in the set direction, replace 1 and -1 by default_scale_x and -default_scale_x.

2 Likes

Yes, this should very well fix i presume

1 Like

thank you so much for the suggestion! if you could please point out where you think this would fit I’d be extremely greatful ( :

I’ll try that, honestly wanted to see if any simpler options worked first, but still thanks a bunch

I’m not gonna lie, I have no idea how to implement this. sorry, but could you elaborate on your idea? I understand the general premise of what it does, just not how to add this into the code :downcast_face_with_sweat:

@P.Annoyingg can you show the node’s scale that contains the sprite? like the scale of your sprite,AnimatedSprite? show us the scale of every node that contains your player sprite

I meant the transform panel:

1 Like

In your other post about this you wrote that you set your sprite scale to 2/2.

In your code you do:
sprite.scale.x = -1 if cardinal_direction == Vector2.LEFT else 1
And change scale. Either make it *-1 and *1 to keep the scale

Or better use sprite.flip_h:
sprite.flip_h = cardinal_direction == Vector2.LEFT:

the sprite2D node

everything else is 1,1
i was resizing the sprite so that it better fit in my environment

1 Like

Then must be a dumb thing hidden in the spaghetti

really sorry, but could you elaborate on that? im admittedly horrible at coding–

There you have it. Your sprite scale is x: 2.0 and y: 2.0.
You have a function called SetDirection() that has this line:

sprite.scale.x = -1 if cardinal_direction == Vector2.LEFT else 1

So when this runs, the sprite scale becomes X: 1.0 (or -1.0) and Y remains 2.0. So the sprite is squashed horizontally.

The actual easiest way I think you can prevent this is by making the actual sprite node scale X: 1.0 and Y: 1.0, and make a new Node2D just to be the parent of the sprite. Then scale the parent node to whatever scale you want the sprite to be (in your case, X: 2 and Y:2) without changing the actual sprite node scale.
That way, when you set the sprite’s X scale to either 1 or -1, it won’t get squashed horizontally.

Or just use sprite.flip_h as iOSxcOder suggested instead of setting the x scale to -1.

2 Likes

This changes the scale to -1 or 1:

sprite.scale.x = -1 if cardinal_direction == Vector2.LEFT else 1

Multiplying by -1 or 1 keeps the scale you set, it’s not programming, it’s math. :grin:

sprite.scale.x = sprite.scale.x *-1 if cardinal_direction == Vector2.LEFT else sprite.scale.x * 1

But if you just want to flip the direction it’s better to not touch the scale and simply use flip_h:
sprite.flip_h = cardinal_direction == Vector2.LEFT:

This returns true or false:
cardinal_direction == Vector2.LEFT

So it flips the sprite only when the cardinal direction is Vector2.LEFT.

1 Like

Multiplying by 1 or -1 won’t work because if it’s already negative multiplying it by 1 won’t (un)flip it, and it will flip to the wrong side the second time it multiplies to -1.
Using flip_h is the way to go.

Just watched this video and there is a chapter about flipping sprites.

1 Like