user: How can you write a first person controller script in GDscript and apply it to a KinematicBody-node when using Godot Engine 3.x and what is the equivalent to the KinematicBody-node in Godot Engine 4.x and how does the first person controller script need to be changed to work in Godot Engine 4.x?

assistant: In Godot Engine 3.x, you can write a first person controller script in GDscript by creating a new script and attaching it to a KinematicBody node. Here is an example of a basic first person controller script:
```csharp
extends KinematicBody

var speed = 5
var mouse_sensitivity = 0.1
var jumping = false
var jump_speed = 10
var gravity = -20
var jump_height = 1.5
var jump_sustain = 0.1

func _input(event):
    if event is InputEventMouseMotion:
        rotation_degrees.y -= event.relative.x * mouse_sensitivity
        rotation_degrees.x = clamp(rotation_degrees.x + event.relative.y * mouse_sensitivity, -90, 90)
    
    if event is InputEventKey and event.pressed and event.scancode == KEY_W:
        var velocity = speed * Vector3(0, 0, 1)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move_and_slide(velocity)
        
    if event is InputEventKey and event.pressed and event.scancode == KEY_S:
        var velocity = speed * Vector3(0, 0, -1)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move_and_slide(velocity)
        
    if event is InputEventKey and event.pressed and event.scancode == KEY_A:
        var velocity = speed * Vector3(-1, 0, 0)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move_and_slide(velocity)
        
    if event is InputEventKey and event.pressed and event.scancode == KEY_D:
        var velocity = speed * Vector3(1, 0, 0)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move_and_slide(velocity)
        
    if event is InputEventKey and event.pressed and event.scancode == KEY_SPACE and not jumping:
        jumping = true
        var velocity = Vector3(0, jump_speed, 0)
        move_and_slide(velocity)
        
func _physics_process(delta):
    if jumping:
        var velocity = move_and_slide(Vector3(0, gravity * delta, 0))
        if velocity.y < 0:
            jumping = false
```

In Godot Engine 4.x, the equivalent to the KinematicBody node is the CharacterController node. To use this node, you will need to change your script to inherit from the CharacterController class. Additionally, the input handling and movement control will be different, as the CharacterController node uses a different API. Here is an example of how the first person controller script would look in Godot Engine 4.x:
```
extends CharacterController

var speed = 5
var mouse_sensitivity = 0.1
var jumping = false
var jump_speed = 10
var gravity = -20
var jump_height = 1.5
var jump_sustain = 0.1

func _input(event):
    if event is InputEventMouseMotion:
        rotation_degrees.y -= event.relative.x * mouse_sensitivity
        rotation_degrees.x = clamp(rotation_degrees.x + event.relative.y * mouse_sensitivity, -90, 90)

    if event is InputEventKey and event.pressed and event.scancode == KEY_W:
        var velocity = speed * Vector3(0, 0, 1)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move(velocity)
    
    if event is InputEventKey and event.pressed and event.scancode == KEY_S:
        var velocity = speed * Vector3(0, 0, -1)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move(velocity)
    
    if event is InputEventKey and event.pressed and event.scancode == KEY_A:
        var velocity = speed * Vector3(-1, 0, 0)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move(velocity)
    
    if event is InputEventKey and event.pressed and event.scancode == KEY_D:
        var velocity = speed * Vector3(1, 0, 0)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move(velocity)
    
    if event is InputEventKey and event.pressed and event.scancode == KEY_SPACE and not jumping:
        jumping = true
        var velocity = Vector3(0, jump_speed, 0)
        velocity = velocity.rotated(Vector3(0, 1, 0), -rotation.y)
        move(velocity)
    
func _physics_process(delta):
    if jumping:
        var velocity = move(Vector3(0, gravity * delta, 0))
    if velocity.y < 0:
        jumping = false
```

Note: The `move` method replaces the `move_and_slide` method from Godot Engine 3.x, and it uses the CharacterController API to handle movement.

user: Could you explain the _physics_process function?

assistant: The purpose of both snippets is to simulate the behavior of a jumping game object in the game. If the game object is in a jumping state (indicated by the "jumping" variable), it will be moved upward with an upward velocity equal to the product of gravity and delta time (gravity * delta).

In the Godot 3.x code, the move_and_slide() function is used to apply the velocity to the game object. This function is used to move a KinematicBody node and have it slide along colliders.

In the Godot 4.x code, the move() function is used to apply the velocity to the game object. This function is used to move a RigidBody node.

Both code snippets check if the velocity of the game object has a negative y component, meaning it is moving downwards. If this is the case, the "jumping" variable is set to false, indicating that the game object has landed and is no longer jumping.