Gravity not applying on player properly - holding on to the ceiling

Godot Version

Godot v4.2.2.stable.official

Question

Gravity not applying on player properly - Godot4, gdscript, 2d platformer, beginner

I am a beginner to both Godot, gdscript, and I have a basic understanding of coding. I am making a game for my school project. The game has a player with a gun that has recoil and pushes the player in the opposite direction of fire. It is a 2d platformer and the character is affected by gravity. Everything works fine until the player shoots down and collides with the tile map/ceiling. If the gun is still shooting down and the player is backed up against the ceiling he doesn’t fall. The gun doesn’t have enough power to keep him in the air as the gravity starts pulling him down after a short time so I’m not sure what’s causing the issue. The player has 3 collision areas one for the body and head and two for the feet. I was thinking of making the game check if his feet are on the ground and then apply gravity, but I’m a bit stuck on how to make that work. Are there any solutions/better solutions to this? If someone can help me I would be very happy! - Sorry if it looks like spaghetti :sweat_smile:

Visual /

Blockquote
extends CharacterBody2D

const SPEED = 200.0
const JUMP_VELOCITY = -380.0

Get the gravity from the project settings to be synced with RigidBody nodes.

var gravity = ProjectSettings.get_setting(“physics/2d/default_gravity”)

@onready var anim : AnimatedSprite2D = $AnimatedSprite2D
@onready var gun : AnimatedSprite2D = $AnimatedSprite2D2
@onready var bullet = preload(“res://Prefab/ak_bullet.tscn”)
var shooting = false
var reloading = false
var x_knock_back = 1.5
var y_knock_back = 3
var bullet_count = 30
var HEALTH = 100
var shots_shot = 0
var mag_reloaded = 0
var healing = false

func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
velocity.y += gravity * delta
if shooting == false and $AnimatedSprite2D2.animation == “Shoot” and reloading == false:
gun.play(“Idle”)
#Walking and direction.
else:
if velocity.x > 10:
anim.play(“Run Right”)
if shooting == false and reloading == false:
gun.play(“Walk”)
elif velocity.x < 0:
anim.play(“Run Left”)
if shooting == false and reloading == false:
gun.play(“Walk”)
else:
anim.play(“Idle”)
if shooting == false and reloading == false:
gun.play(“Idle”)

# Gun Aiming.
gun.look_at(get_global_mouse_position())
if get_global_mouse_position().x < position.x:
	gun.flip_h = true
	gun.scale = Vector2(-1,-1)
else:
	gun.flip_h = false
	gun.scale = Vector2(1,1)

if Input.is_action_pressed("Left Click"):
	if bullet_count > 0 and reloading == false:
		shooting = true
		gun.play("Shoot")
		if shooting == true and not is_on_floor():
			anim.play("Fly")
		var dis_diff = (position - get_global_mouse_position()).normalized()
		position.x = position.x + (dis_diff.x * x_knock_back)
		if not is_on_floor():
			position.y = position.y + (dis_diff.y * y_knock_back)
		if $Cooldown.is_stopped():
			$Cooldown.start()
			var new_bullet = bullet.instantiate()
			new_bullet.look_at((position - get_global_mouse_position())*-1)
			new_bullet.position = gun.global_position 
			new_bullet.rotation = gun.rotation + randf_range(-0.08,0.08)
			get_parent().add_child(new_bullet)
			shots_shot += 1
			bullet_count = bullet_count - 1  
			
	else:
		if reloading == false:
			reloading_gun()
	
else:
	shooting = false

if Input.is_action_pressed("R") and shooting == false and reloading == false:
	reloading_gun()

if HEALTH <= 0:
	queue_free()

# Handle jump.
if Input.is_action_pressed("Up") and is_on_floor():
	velocity.y = JUMP_VELOCITY
	anim.play("Jump")
	if reloading == false:
		gun.play("Jump")

# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("Left", "Right")
if direction:
	velocity.x = direction * SPEED
else:
	velocity.x = move_toward(velocity.x, 0, SPEED)

if $HealthTick.is_stopped() and healing == false and HEALTH > 0:
	healing = true
	HEALTH += 1
	$HealthTick.start()
	healing = false

$CanvasLayer/Ammo.value = bullet_count
$CanvasLayer/Health.value = HEALTH

move_and_slide()

func reloading_gun():
reloading = true
gun.play(“Reload”)
await get_tree().create_timer(2).timeout
bullet_count = 30
mag_reloaded += 1
reloading = false

func _on_area_2d_area_entered(area):
if area.is_in_group(“bullet1”):
HEALTH -= 12
elif area.is_in_group(“bullet2”):
HEALTH -= 2
elif area.is_in_group(“bullet3”):
HEALTH -= 3
else:
pass

Blockquote

Firstly, you didn’t have to write shooting == false, since == returns another true or false value (which we called a bool). Use not shooting instead, not will flip true to false, and false to true. Secondly, try to use code format for all of your code, the code format displays as follows:

```gdscript ← This specifies the language of this block of code

Write or paste your code in here

```

As for this code, you can apply gravity without checking whether the player is on the floor.

1 Like

I changed that line of code but the character still continues to hang from the tile map in the same way as before

The issue might caused by this section. Since you only changed the position, while the velocity is still simulating, it can cause unexpected and weird problems.

Consider adding a certain force to the velocity, or setting it to a fixed value, as you handle the jump action.

1 Like

I ended up changing the "position.y"s to “velocity.y” which seemed to solve the problem but made the knockback much weaker, so all I did was triple the knockback value which fixed it. Thank you so much!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.