Loading...
Loading...
Implement 2D kinematic character movement in Godot 4.x with CharacterBody2D and move_and_slide(): platformer run/jump with gravity, top-down 8-direction motion, slope handling, and reading collisions. Use when coding a 2D player or enemy controller, a platformer or top-down character, or fixing move_and_slide()/ is_on_floor() behavior in a .tscn with a CharacterBody2D.
npx skill4agent add gamedev-skills/awesome-gamedev-agent-skills godot-2d-movementCharacterBody2Dmove_and_slide()move_and_slide()is_on_floor()godot-physicsgodot-tilemapplatformerphysics-tuningCharacterBody2DCollisionShape2Dvelocitymove_and_slide()velocityvelocity_physics_process(delta)move_and_slide()velocitydeltavelocity.yvelocity.yis_on_floor()motion_mode = MOTION_MODE_FLOATINGis_on_floor()is_on_wall()get_wall_normal()get_slide_collision(i)extends CharacterBody2D
@export var speed := 200.0
@export var jump_velocity := -400.0
@export var gravity := 1200.0 # pixels/sec^2 (tune to taste)
func _physics_process(delta: float) -> void:
# Apply gravity while airborne.
if not is_on_floor():
velocity.y += gravity * delta
# Jump only when grounded (Input action set in Project Settings > Input Map).
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
# Horizontal input: -1, 0, or 1.
var dir := Input.get_axis("move_left", "move_right")
if dir != 0.0:
velocity.x = dir * speed
else:
velocity.x = move_toward(velocity.x, 0.0, speed) # decelerate to a stop
move_and_slide() # 4.x: no arguments; uses and updates `velocity`extends CharacterBody2D
@export var speed := 220.0
func _ready() -> void:
motion_mode = CharacterBody2D.MOTION_MODE_FLOATING # no floor/ceiling concept
func _physics_process(_delta: float) -> void:
# get_vector returns a normalized-ish Vector2 from four input actions.
var input := Input.get_vector("move_left", "move_right", "move_up", "move_down")
velocity = input * speed
move_and_slide()func _physics_process(delta: float) -> void:
# ... set velocity ...
move_and_slide()
for i in get_slide_collision_count():
var c := get_slide_collision(i)
var other := c.get_collider()
if other and other.is_in_group("enemies"):
take_damage(1) # touched an enemy while moving@export var coyote_time := 0.1
var _coyote := 0.0
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
_coyote -= delta
else:
_coyote = coyote_time
if Input.is_action_just_pressed("jump") and _coyote > 0.0:
velocity.y = jump_velocity
_coyote = 0.0
# ... horizontal input + move_and_slide() ...move_and_slide(velocity)velocitymove_and_slide()move_and_slide(velocity, Vector2.UP)move_and_slide()velocity = dir * speed * delta_process_physics_process_physics_processis_on_floor()up_directionVector2.UPCollisionShape2Dmove_and_slide()position +=move_and_slide()floor_stop_on_slope = truefloor_snap_lengthmove_and_collide()references/controller-recipes.mdgodot-physicsgodot-tilemapgodot-animationcamera-systemsplatformerinput-systems