Godot Version
4.2.2
Question
Hello, I’m new to Godot and i’m trying to make the player (CharacterBody2D) squeeze when i press a certain key. and unsqueeze if there’s no ceiling over it. i made the squeezing part work but it seems to not care about ceilings and vibrate up and down when it tries to unsqueeze under a ceiling
This the code im using right now
if Input.is_action_pressed("squish") and $CollisionShape2D.scale.y > 0.25:
$CollisionShape2D.scale.y -= 0.015625
$CollisionShape2D.position.y += 1
$Sprite2D.position.y += 1
$Sprite2D.scale.y -= 0.015625
elif $CollisionShape2D.scale.y < 1 and not is_on_ceiling():
print(is_on_ceiling())
$CollisionShape2D.scale.y += 0.015625
$CollisionShape2D.position.y -= 1
$Sprite2D.position.y -= 1
$Sprite2D.scale.y += 0.015625
Thanks in advance!
I’m not sure if that will be the cause of problem but Godot documentation explict says to not change CollisionShape2D scale and that can result in unexpected behavior
From Godot physics introdution documentation:
Important
Be careful to never scale your collision shapes in the editor. The “Scale” property in the Inspector should remain (1, 1)
. When changing the size of the collision shape, you should always use the size handles, not the Node2D
scale handles. Scaling a shape can result in unexpected collision behavior.
So i recommend you start from there
I changed my code to use shape size handles. but it still has the same results.
Here’s the new code
if Input.is_action_pressed("squish") and $CollisionShape2D.shape.size.y > 32:
$CollisionShape2D.shape.size.y -= 1
$CollisionShape2D.position.y += 1
$Sprite2D.position.y += 1
$Sprite2D.scale.y -= 0.0078125
elif $CollisionShape2D.shape.size.y < COLLISION_SHAPE_Y and not is_on_ceiling():
$CollisionShape2D.shape.size.y += 1
$CollisionShape2D.position.y -= 1
$Sprite2D.position.y -= 1
$Sprite2D.scale.y += 0.0078125
Can you share the project for me take a look?
sure thing. i cant seem to be able to send it here as a zip. where can i send it to you?
Upload on github or drive
I think i found what is happening, when you make the collision shape bigger inside the gasp is_on_ceiling will be true only when the shape reach the size of the gasp, the problem is the shape will have a collision conflict with the floor/ceiling because will invade their shapes, so the physics engine will try push the character shape away to not let him insde the floor/ceiling, that fight is the flicking that you see the character going up and down, and to make worse, while the physics engine fight to not let the player shape enter in the ceiling shape, will make is_on_ceiling be false and the size will keep increase making the conflict even worse.
The solution is use another way to check if player reach the size, in this case an Area2D node:
Create an Area2D node with a CollisionShape2D as child and put a RectagleShape2D as shape like the image bellow:
In your code make this changes:
elif Input.is_action_just_pressed("jump"):
velocity.y = JUMP_VELOCITY
# Keep the area in the correct position
$Area2D.global_position.y = $CollisionShape2D.global_position.y + ($CollisionShape2D.shape.size.y / -2) - 1
# Squeeze code
if Input.is_action_pressed("squish") and $CollisionShape2D.shape.size.y > 32:
$CollisionShape2D.shape.size.y -= 1
$CollisionShape2D.position.y += 1
$Sprite2D.position.y += 1
$Sprite2D.scale.y -= 0.0078125
# Check if the shape y size is small than the final size and check if something is inside the area shape
elif $CollisionShape2D.shape.size.y < COLLISION_SHAPE_Y and $Area2D.get_overlapping_bodies().size() == 0:
$CollisionShape2D.shape.size.y += 1
$CollisionShape2D.position.y -= 1
$Sprite2D.position.y -= 1
$Sprite2D.scale.y += 0.0078125
# Get the input direction and handle the movement/deceleration.
var direction = Input.get_axis("move_left", "move_right")
With that your game will work as expected:
2 Likes
this worked for me but i had to make it
$Area2D.global_position.y = $CollisionShape2D.global_position.y + ($CollisionShape2D.shape.size.y / -2) - 1 + COLLISION_SHAPE_Y
Thanks! This was very helpful. I will make sure to credit you in the game if it ever gets completed.
1 Like
But this introduced a new issue. the player can’t unqueeze while mid air. using the Area2D’s body_entered signal i can see that the Area2D is colliding with the CharacterBody2D (the player)
I tried to make it higher but it still somehow collides with the player. could you help?
On the platforms in the collsion tab, turn on the layer 2 and in the Area2D turn off layer 1 and mask 1 and turn on mask 2. This way the area will only detect the platforms, also make sure your Area2D have at least 3 pixels size in the y axis, i’ll send the project with the corrections if you want to check more precisily
1 Like
thanks this worked for me.
for some reason i had issues where i couldnt jump while unsqueezing when i copied over your player scene to my project it worked
also:
$Area2D.global_position.y = $CollisionShape2D.global_position.y + ($CollisionShape2D.shape.size.y / -2) - 1
i had to use again.
i guess i missed up my player position or something.
Thank you very much! without your help i couldnt have solved this issue.