• Godot Help2D
  • Flipping the Player sprite with its CollisionShape2D

Hi,
Up until now I've used $AnimatedSprite.flip_h = true / $AnimatedSprite.flip_h = false to flip the Player sprite.

However I'm using the free Kings and Pigs asset pack where the Player character has a large hammer.

Obviously the CollisionShape2D does not flip along with the $AnimatedSprite.

So instead I tried another method which was suggested online, scaling the Player with:

scale.x =  scale.y * 1
scale.x =  scale.y * -1

It does the trick, however there is an issue when the Player flips direction, he isn't centred - the overall sprite is flipped which makes the character off-centre. This obviously causes a problem when standing on a platform ledge, he naturally falls off when you change direction.

I tried moving the Player's animated sprite to be off-centre, but that doesn't seem to work.

I need the Player sprite to stay fixed from his centre, not including the hammer.
Any ideas?

Here's the script for reference:

extends KinematicBody2D

# Move Player Left/Right with Variable Jump Height


var myVelocity = Vector2() #Store vector coorinates in the variable myVelocity
var onGround = false

const PLAYERSPEED = 90
const GRAVITY = 15
const JUMPPOWER = -300
const JUMPLOW = -150
const FLOOR = Vector2(0,-1)


func _physics_process(delta):	
	
	myVelocity.x = 0
	
	# MOVE PLAYER LEFT/RIGHT
	if Input.is_action_pressed("ui_right"):
		myVelocity.x = PLAYERSPEED
		$AnimatedSprite.play("Walk")
		scale.x =  scale.y * 1
		#$AnimatedSprite.flip_h = false
	elif Input.is_action_pressed("ui_left"):
		myVelocity.x = -PLAYERSPEED
		$AnimatedSprite.play("Walk")
		scale.x =  scale.y * -1
		#$AnimatedSprite.flip_h = true
	else:
		myVelocity.x = 0
		if onGround == true:
			$AnimatedSprite.play("Idle")
		
	# JUMP		
	if Input.is_action_pressed("ui_up") && is_on_floor():
		myVelocity.y = JUMPPOWER
		
	# VARIABLE JUMP HEIGHT		
	if Input.is_action_just_released("ui_up"):
		myVelocity.y = -JUMPLOW	
		
		
	myVelocity.y += GRAVITY # Add gravity to the Player
	

	# Set if on the ground or not
	if is_on_floor():
		onGround = true
	else:
		onGround = false
		if myVelocity.y < 0:
			$AnimatedSprite.play("Jump")
		else:
			$AnimatedSprite.play("Fall")	
	
	
	myVelocity = move_and_slide(myVelocity, FLOOR) # Move Player 
  • Hi,

    Thanks for the repsonses.

    One of the problems with using a Node2D as the parent of the AnimatedSprite is that the attached CollisionShape2D will no longer work - you get a warning. When in game the Player will fall through the platforms. I read elswhere online a similar suggestion.

    My work-around was similar, instead of adding another Node2D as suggested, I just scaled the root node (Kinematic2D), e.g.

    	if Input.is_action_pressed("ui_right"):
    		myVelocity.x = PLAYERSPEED
    		$AnimatedSprite.play("Walk")
    		$".".scale.x =  scale.y * 1
    		
    		#$AnimatedSprite.flip_h = false
    	elif Input.is_action_pressed("ui_left"):
    		myVelocity.x = -PLAYERSPEED
    		$AnimatedSprite.play("Walk")
    		$".".scale.x =  scale.y * -1
    		#$AnimatedSprite.flip_h = true
    	else:
    		myVelocity.x = 0
    		if onGround == true:
    			$AnimatedSprite.play("Idle")

    I recentered the Player to the origin of the world also along with it's CollisionShape2D.

Why not just move the collision area when you flip the sprite? Or if you want to stick to scaling, move the sprite when you change the scale.

You can add another Node2D on top of the Sprite (under your player) and then flip that. That way you can control the positioning/centering within the Node2D, so the Sprite is in the real center (not the image center).

Hi,

Thanks for the repsonses.

One of the problems with using a Node2D as the parent of the AnimatedSprite is that the attached CollisionShape2D will no longer work - you get a warning. When in game the Player will fall through the platforms. I read elswhere online a similar suggestion.

My work-around was similar, instead of adding another Node2D as suggested, I just scaled the root node (Kinematic2D), e.g.

	if Input.is_action_pressed("ui_right"):
		myVelocity.x = PLAYERSPEED
		$AnimatedSprite.play("Walk")
		$".".scale.x =  scale.y * 1
		
		#$AnimatedSprite.flip_h = false
	elif Input.is_action_pressed("ui_left"):
		myVelocity.x = -PLAYERSPEED
		$AnimatedSprite.play("Walk")
		$".".scale.x =  scale.y * -1
		#$AnimatedSprite.flip_h = true
	else:
		myVelocity.x = 0
		if onGround == true:
			$AnimatedSprite.play("Idle")

I recentered the Player to the origin of the world also along with it's CollisionShape2D.

4 months later

Thank you so much! I tried to register (only to realize I already had an account here xD) just to thank you for that solution, the collision issue in my game was driving me nuts!!