Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Recursos do controle

O Godot suporta recursos específicos de controle que podem aprimorar ainda mais a experiência de jogo. Esta página descreve esses recursos, como jogos existentes os utilizaram e como você pode começar a usá-los no Godot.

Aviso

Estes recursos de controle são atualmente suportados apenas no Windows, macOS, iOS e Linux.

Aviso

A menos que você anuncie especificamente que seu jogo exige controles específicos, lembre-se de que não há garantia de que os jogadores terão um controle com determinados recursos.

Como resultado, sugerimos o uso desses recursos para aprimorar a experiência de jogo dos jogadores cujos controles os suportam, sem prejudicar aqueles que não possuem tais controles.

Cor do LED

Os jogos podem usar as luzes LED de certos controles para complementar sutilmente a jogabilidade na tela, fornecendo alguns visuais correspondentes nas mãos do jogador. Aqui estão alguns exemplos notáveis:

  • Em Hades, a cor da luz corresponde ao deus do qual você está recebendo uma bênção.

  • Em Resident Evil 2, a cor da luz indica sua saúde (verde para cheia, amarelo para média, vermelho para baixa).

  • Em Star Wars Jedi: Fallen Order, a cor da luz corresponde à cor do seu sabre de luz.

Use o método Input.set_joy_light() para definir a cor dos LEDs de um determinado controle.

Para determinar se um determinado controle suporta a definição de luzes LED, use o método Input.has_joy_light(). Os controles DualShock e DualSense do PlayStation são conhecidos por suportar luzes LED.

O seguinte método _process() define a cor do LED de acordo com o botão pressionado atualmente e o desliga se nenhum botão estiver sendo pressionado:

func _process(_delta):
    var color := Color.BLACK

    if Input.is_joy_button_pressed(0, JOY_BUTTON_A):
        color = Color.BLUE
    elif Input.is_joy_button_pressed(0, JOY_BUTTON_X):
        color = Color.MAGENTA
    elif Input.is_joy_button_pressed(0, JOY_BUTTON_B):
        color = Color.RED
    elif Input.is_joy_button_pressed(0, JOY_BUTTON_Y):
        color = Color.GREEN

    Input.set_joy_light(0, color)

O exemplo a seguir esmaece suavemente o LED através de matizes em um loop:

var hue = 0.0

func _process(delta):
    var col = Color.from_hsv(hue, 1.0, 1.0)
    Input.set_joy_light(0, col)
    hue += delta * 0.1

O exemplo a seguir faz o LED piscar em vermelho três vezes quando o botão sul (Cross/X nos controles de PlayStation) é pressionado:

var blink_tween: Tween = null

func _process(_delta):
    var ready_to_blink = not blink_tween or not blink_tween.is_running()
    if Input.is_joy_button_pressed(0, JOY_BUTTON_A) and ready_to_blink:
        do_blink()

func do_blink():
    if blink_tween:
        blink_tween.kill()

    blink_tween = create_tween()
    blink_tween.tween_callback(func(): Input.set_joy_light(0, Color.RED))
    blink_tween.tween_interval(0.2)
    blink_tween.tween_callback(func(): Input.set_joy_light(0, Color.BLACK))
    blink_tween.tween_interval(0.2)
    blink_tween.set_loops(3)

Sensores de movimento (giroscópio e acelerômetro)

Com os controles de movimento, os jogos podem rastrear a rotação física e o movimento do controle. Isso pode ser usado para permitir que o jogador gire a câmera do jogo movendo o controle, ou balance o controle para realizar uma ação especial.

Existem várias marcas de controles que implementaram sensores de giroscópio e acelerômetro em seus controles modernos, sendo as duas maiores a PlayStation e a Nintendo. Note que os controles de Xbox não possuem sensores de movimento dentro deles.

Para verificar se um controle conectado possui sensores de movimento, use Input.has_joy_motion_sensors().

Os sensores de movimento ficam desativados por padrão para evitar o esgotamento da bateria do controle quando os jogos não usam esses recursos. Para ativá-los, chame Input.set_joy_motion_sensors_enabled().

Note que os eixos dos valores que os sensores de movimento do controle relatam são sempre relativos à orientação natural do controle. Aqui está uma imagem do mapeamento dos eixos para maior clareza:

../../_images/controller_axes.webp

Os valores do giroscópio do controle mostram a rotação em torno de seus respectivos eixos:

  • the X value of the gyroscope data shows the rotation around the X axis (pitch).

  • o valor Y dos dados do giroscópio mostra a rotação em torno do eixo Y (guinada/yaw).

  • the Z value of the gyroscope data shows the rotation around the Z axis (roll).

O acelerômetro do controle fornecerá valores das seguintes maneiras, respectivamente:

  • Movimentos para a esquerda e para a direita são relatados como +X e -X.

  • Movimentos para baixo e para cima são relatados como +Y e -Y.

  • Movimentos para longe e em direção ao usuário são relatados como +Z e -Z.

Giroscópio

Um giroscópio é um tipo de sensor que detecta a rotação do controle. Aqui estão alguns exemplos notáveis do uso de giroscópio em jogos:

  • Em Helldivers 2, Horizon Forbidden West, Star Wars: Dark Forces Remaster e Fortnite, inclinar o controle faz com que a câmera gire de acordo ("mira por giroscópio"). Este vídeo de *Daven On The Moon* demonstra e discute a mira por giroscópio em mais detalhes.

  • Em Death Stranding, o BB pode ser acalmado rotacionando o controle suavemente.

O exemplo a seguir rotaciona um objeto usando o sensor de giroscópio de um controle. Você também pode acessar este exemplo dando uma olhada na documentação de Input.start_joy_motion_sensors_calibration().

const GYRO_SENSITIVITY = 10.0

func _ready():
    # In this example we only use the first connected joypad (id 0).
    if 0 not in Input.get_connected_joypads():
        return

    if not Input.has_joy_motion_sensors(0):
        return

    # We must enable the motion sensors before using them.
    Input.set_joy_motion_sensors_enabled(0, true)

    # (Tell the users here that they need to put their joypads on a flat surface and wait for confirmation.)

    # Start the calibration process.
    calibrate_motion()

func _process(delta):
    # Only move the object if the joypad motion sensors are calibrated.
    if Input.is_joy_motion_sensors_calibrated(0):
        move_object(delta)

func calibrate_motion():
    Input.start_joy_motion_sensors_calibration(0)

    # Wait for some time.
    await get_tree().create_timer(1.0).timeout

    Input.stop_joy_motion_sensors_calibration(0)
    # The joypad is now calibrated.

func move_object(delta):
    var node: Node3D = ... # Put your object here.

    var gyro := Input.get_joy_gyroscope(0)
    node.rotation.x -= -gyro.y * GYRO_SENSITIVITY * delta  # Use rotation around the Y axis (yaw) here.
    node.rotation.y += -gyro.x * GYRO_SENSITIVITY * delta  # Use rotation around the X axis (pitch) here.

Observe que, antes de usar os dados do giroscópio, devemos primeiro calibrá-lo chamando Input.start_joy_motion_sensors_calibration() e Input.stop_joy_motion_sensors_calibration(). Isso ocorre porque os giroscópios modernos frequentemente precisam de calibração. Isso é semelhante a como uma balança de pesagem pode precisar de calibração para saber o que é o "zero". Assim como uma balança, apenas um giroscópio corretamente calibrado fornecerá uma leitura precisa. Durante a calibração, o usuário coloca o controle sobre uma superfície plana. O controle então determina quais valores seu giroscópio relata quando ele está realmente sem nenhum movimento (seu "viés"/bias) e usa essa informação para tornar os dados de rotação mais precisos.

Consulte o artigo na GyroWiki para obter informações sobre como usar a entrada do giroscópio como um mouse.

Depois que o giroscópio do controle tiver sido ativado e calibrado corretamente, você poderá ler seus valores relatados usando Input.get_joy_gyroscope().

Acelerômetro

Aviso

Não use dados do acelerômetro para encontrar a posição do controle no espaço 3D; os acelerômetros em geral não são precisos o suficiente para isso.

Um acelerômetro é um tipo de sensor que detecta a aceleração de um controle em m/s². Por exemplo, ele pode detectar se o jogador levanta rapidamente o controle, move-o para o lado ou o balança.

A aceleração que um acelerômetro detecta inclui a gravidade por padrão. Para obter apenas a aceleração aplicada pelo usuário, subtraia a gravidade da aceleração detectada:

Input.get_joy_accelerometer(device) - Input.get_joy_gravity(device)

Devido ao funcionamento físico dos acelerômetros, após a interrupção do movimento em uma direção, eles relatam quase imediatamente um movimento na direção oposta. Depois de detectar o movimento em uma direção, você pode querer ignorar leituras adicionais por um curto período de tempo para evitar a detecção desse movimento oposto.

O exemplo a seguir imprime o movimento do controle quando ele está sendo movido rapidamente usando seu acelerômetro. Se a sensibilidade não parecer correta para você, você pode ajustar a constante THRESHOLD ou substituí-la usando um valor diferente no código abaixo.

var detect_accelerometer = true

# Change to make the game detect movement at different thresholds.
# With a lower value, smaller movements will be detected, and with a
# larger value, only big movements will be detected.
const THRESHOLD = 10.0

func _ready():
    # In this example, we only use the first connected joypad (ID 0).
    if 0 not in Input.get_connected_joypads():
        return

    if not Input.has_joy_motion_sensors(0):
        return

    # We must enable the motion sensors before using them.
    Input.set_joy_motion_sensors_enabled(0, true)

func _process(delta):
    if Input.has_joy_motion_sensors(0):
        accelerometer_example()

func accelerometer_example():
    if not detect_accelerometer:
        return

    var acceleration = Input.get_joy_accelerometer(0) - Input.get_joy_gravity(0)
    if acceleration.length() > THRESHOLD:
        if acceleration.x > THRESHOLD:
            print("Moved left")
        elif acceleration.x < -THRESHOLD:
            print("Moved right")
        if acceleration.y < -THRESHOLD:
            print("Moved up")
        elif acceleration.y > THRESHOLD:
            print("Moved down")
        if acceleration.z < -THRESHOLD:
            print("Moved closer to the player")
        elif acceleration.z > THRESHOLD:
            print("Moved away from the player")

        # After detecting movement in one direction, the accelerometer sensor
        # will briefly report movement in the opposite direction, even though the controller only moved once.
        # So we need to ignore these reported values for a short amount of time.
        detect_accelerometer = false
        await get_tree().create_timer(0.5, false).timeout
        detect_accelerometer = true