Creating and Using QPlatformerBodyNode - erayzesen/godot-quarkphysics GitHub Wiki

QPlatformerBodyNode

QPlatformerBodyNode is a type of QBodyNode designed to solve all the problems users might face with the physics engine in traditional platformer characters while also providing the necessary methods.

How to Create a QPlatformerBodyNode? You can create a QPlatformerBodyNode object by adding it to the scene tree just like any other node. If you add child nodes such as QMeshRectNode, QMeshPolygonNode, QMeshCircleNode, or custom-designed QMeshAdvancedNode under it, your QPlatformerBodyNode will be ready to work in the basic sense. You can also make the necessary adjustments via the Inspector. Additionally, it is possible to add it via code.

var player=QPlatformerBodyNode.new()
player.global_position=Vector2(500,500)
add_child(player)

var my_mesh=QMeshRectNode.new()
my_mesh.rectangle_size=Vector2(128,128)
player.add_child(my_mesh)


How Does QPlatformerBodyNode Work?

QPlatformerBodyNode is actually a class that inherits from QRigidBodyNode. However, it disables velocity integrators and gravity-related behaviors of the world, essentially using the physics engine as a collider while applying its own movement logic.

It has a gravity parameter, which determines the movement direction. Based on this gravity direction, it applies a two-axis approach using horizontal_velocity and vertical_velocity, which store the character’s velocity values.

  • The walk() method moves the character on the horizontal axis.
  • The jump() method makes the character perform a jump on the vertical axis.

It automatically handles movement on slopes and sticking to moving platforms based on the configurations you set. Additionally, it provides various methods to query the surrounding physics world( get_left_wall(offset), get_right_wall(offset), get_floor(offset), get_ceiling(offset) ) and control the horizontal and vertical velocities.

How to Use QPlatformerBodyNode?

Creating a basic platformer character with QPlatformerBodyNode requires very little code, allowing you to quickly complete a prototype.

For example, the following code is sufficient for a walking and jumping platformer character with default inspector settings:

extends QPlatformerBodyNode

func _ready() -> void:
  pass

func _physics_properties(delta: float) :
  #Walk Method: walk(side:int)
  var walk_side=int(Input.is_action_pressed("ui_right"))-int(Input.is_action_pressed("ui_left"))
  walk(walk_side)
  #Jump Method : jump(force:float, unconditional:bool)
  if Input.is_action_pressed("ui_up") :
    jump(4.0,false)
  if Input.is_action_just_released("ui_up") :
    release_jump()


However, an important point to note is that the default jump(force:float,unconditional:bool) function works based on built-in platformer logic if you set unconditional parameter as false. In this situation:

  • The character must be on the ground to jump again.
  • The character can jump a maximum of max_jump_count times.
  • The character waits jump_duration_frame_count frames between two jump triggers.

But how can we implement a jump independently of these predefined conditions? How can we take full control over the character’s velocity for a custom mechanic?

The following code demonstrates how to manipulate horizontal and vertical velocities while wall-jumping, making the character move in the direction of the wall’s normal upon jumping. This logic is fully customizable by the developer:

extends QPlatformerBodyNode

func _ready() -> void:
  #Using "collision" signal to handle collisions
  connect("collision",on_collision)
  pass 

	
func _physics_process(delta: float) -> void:
  #Walk 
  var walk_side=int(Input.is_action_pressed("ui_right"))-int(Input.is_action_pressed("ui_left"))
  walk(walk_side)
  #Implementing Wall Friction via the Gravity Multiplier Feature
  var wall_mode:bool=false 
  var wall_offset=3.0
  #Checking Walls according to the offset
  var wall_side= int( get_right_wall(3.0)["body"] !=null ) - int( get_left_wall(3.0)["body"]!=null )
  if get_is_on_floor()==false and wall_side!=0 :
    wall_mode=true
    if get_is_falling() :
      set_gravity_multiplier(0.3)
    else :
      set_gravity_multiplier(1.0)
  else :
      set_gravity_multiplier(1.0)
		
  #Jump 
  if Input.is_action_pressed("ui_up") :
    # If the player is on the Wall
    if wall_mode==true :
      if get_is_jump_released() :
        jump(4.0,true)
        set_controller_horizontal_velocity(Vector2.RIGHT*10.0*-wall_side)
    else :
      #Default Jump
      jump(4.0,false)

  if Input.is_action_just_released("ui_up") :
    release_jump()
		
func on_collision(body,info) :
  var collided_body=info["body"]
  if collided_body is Coin :
    collided_body.queue_free()

Thus, QPlatformerBodyNode not only provides predefined abstracted behaviors but also serves the purpose of allowing developers to extend functionality beyond them.

Can I Develop a Platformer Character Without QPlatformerBodyNode?

Of course. If QPlatformerBodyNode is far from the mechanics and behaviors required for your game, you can create your own platformer character by inheriting from the desired QBodyNode type.

QPlatformerBodyNode Inspector Properties

  • Gravity - gravity: The gravitational force applied to the character, determining the horizontal and vertical axes.
  • Specific Platform Layers -specific_platform_layers : Defines the layers on which the character applies platform-specific behaviors. If not set, the character treats all objects as platforms.

Walking Properties

  • Walk Speed - walk_speed: The character’s movement speed on platforms. Default is 3.
  • Walk Acceleration Rate - walk_aceleration_rate : Determines how quickly the character reaches max speed from rest. Should be between 0 and 1. Default is 0.1.
  • Walk Deceleration Rate - walk_deceleration_rate: Determines how quickly the character slows down to a stop. Should be between 0 and 1. Default is 0.1.

Jumping Properties

  • Max Jump Count - max_jump_count: Determines how many times the character can jump before touching the ground again. Default is 2.
  • Jump Duration Count - jump_duration_count: Specifies how many frames the jump button must be held to trigger a jump. Default is 30.
  • Jump Gravity Multiplier - jump_gravity_multiplier: Controls how much gravity is reduced while the jump button is held. Default is 0.4.
  • Jump Fall Gravity Multiplier - jump_fall_gravity_multiplier: Adjusts the gravity applied when the character is falling. Default is 1.0.

Floor Properties

  • Moving Floor Snap Offset - moving_floor_snap_offset: Determines the maximum vertical distance required for the character to snap onto moving platforms. Default is 10.
  • Floor Max Angle Degree - floor_max_angle_degree: Defines the maximum angle the character can walk on without sliding. Default is 45 degrees. If a platform has a steeper angle, the character will slide.

To learn more about all the methods and properties of QPlatformerBodyNode, refer to the QPlatformerBodyNode page.