Making Platformer Player Movement 2D

platformer mechanics godot 4

Assuming that you have created a simple stage for the game using tile-maps or any other approach. You now want to create a character controller & move it with code in that game level. This 2D platformer player controller recipe solves this problem.

In next recipe, we will see how to shoot bullets or stones in game or throw daggers to kill NPCs. And after that, we will create NPC characters in game.

This recipe is helpful if you have some basic understanding of the Godot engine.

Assets & Project Link

The code of all the platformer tutorial series is present in this repository. All the assets are given credit by linking to their original sources in a.txt files in every folder.

Making a character

In Godot, create a scene with CharacterBody2D as its root. Add a Sprite2D (or AnimatedSprite2D) nodes as its child. Also add collision shape. Overall setup should look like this:

platformer character godot

Motion mechanics

Add a script to the character and add code to move left, right, jump, or stay idle like this (I used AnimatedSprite2D for these animations) if you use Sprite2D, just remove lines dealing with AnimatedSprite2D:


extends CharacterBody2D

@export var speed = 232
@export var jump_speed = -800
@export var gravity = 300 *  9.8

@export_range(0.0, 1.0) var friction = 0.32
@export_range(0.0 , 1.0) var acceleration = 0.32

var is_jumping :bool= false


func _physics_process(delta):
	velocity.y += gravity * delta
	var dir = Input.get_axis("ui_left", "ui_right")
	if dir != 0:
		if is_on_floor():
			velocity.x = lerp(velocity.x, dir * speed, acceleration)
		else:
			velocity.x = lerp(velocity.x, dir * speed * 1.4, acceleration)
		if dir > 0:
			# flip the sprite
			$AnimatedSprite2D.flip_h = false
		else:
			$AnimatedSprite2D.flip_h = true
		$AnimatedSprite2D.play("run")
	else:
		velocity.x = lerp(velocity.x, 0.0, friction)
		$AnimatedSprite2D.play("idle")
	
	if Input.is_action_just_pressed("ui_up") and is_on_floor():
		velocity.y = jump_speed
		is_jumping = true
	
	if is_jumping:
		if is_on_floor():
			is_jumping = false
		$AnimatedSprite2D.play("fall")
	
	move_and_slide()

Adding attack mechanics

Attack adds a bit of complexity. While attacking, we complete the animation even if another animation such as jump or run is triggered. Otherwise, attack animation will be cut abruptly. For this we add some more checks.

sword attack animation platformer game

Code:



extends CharacterBody2D

@export var speed = 232
@export var jump_speed = -800
@export var gravity = 300 *  9.8

@export_range(0.0, 1.0) var friction = 0.32
@export_range(0.0 , 1.0) var acceleration = 0.32

var is_jumping: bool= false
var is_attacking: bool = false


func _physics_process(delta):
	velocity.y += gravity * delta
	var dir = Input.get_axis("ui_left", "ui_right")
	if dir != 0:
		if is_on_floor():
			velocity.x = lerp(velocity.x, dir * speed, acceleration)
		else:
			velocity.x = lerp(velocity.x, dir * speed * 1.4, acceleration)
		if dir > 0:
			# flip the sprite
			$AnimatedSprite2D.flip_h = false
		else:
			$AnimatedSprite2D.flip_h = true
		if not is_attacking: $AnimatedSprite2D.play("run")
	else:
		velocity.x = lerp(velocity.x, 0.0, friction)
		if not is_attacking: $AnimatedSprite2D.play("idle")
	
	if Input.is_action_just_pressed("ui_up") and is_on_floor():
		velocity.y = jump_speed
		is_jumping = true
	
	if is_jumping:
		if is_on_floor():
			is_jumping = false
		if not is_attacking: $AnimatedSprite2D.play("fall")
	
	if Input.is_action_just_pressed("ui_home"):
		is_attacking = true
	
	if is_attacking:
		$AnimatedSprite2D.play("attack")
	
	move_and_slide()


func _on_animated_sprite_2d_animation_finished():
	if is_attacking:
		is_attacking = false
		print("ff")
	


func _on_animated_sprite_2d_animation_looped():
	if is_attacking:
		is_attacking = false
		print("ff")


Thank you for reading <3

Leave a Reply

Your email address will not be published. Required fields are marked *