> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/mouse-movement.md).

# Movimento do rato

Reaja ao movimento do rato do jogador em tempo real, para acionar gestos de arrastar, girar objetos ou controlar câmeras personalizadas.

Sua cena pode ler o movimento bruto do mouse do jogador em cada frame e usá-lo para conduzir interações em tempo real: gestos de arrastar e deslizar, girando ou movendo objetos enquanto o jogador os arrasta, ou controlando uma câmera personalizada como em um jogo de tiro em primeira pessoa.

Para fazer isso, leia o `screenDelta` property do `PrimaryPointerInfo` componente em `engine.RootEntity`. Esta propriedade é um `Vector2` que informa quantos pixels o mouse se moveu desde o último frame. Valores positivos de `x` significam que o mouse se moveu para a direita, valores positivos de `y` significam que ele se moveu para baixo, correspondendo à origem da tela no canto superior esquerdo — o mesmo espaço de coordenadas de `UiTransform` e `UiCanvasInformation`. Nos frames em que o mouse não se move, ambos os valores são 0.

```ts
import { engine, PrimaryPointerInfo } from '@dcl/sdk/ecs'

engine.addSystem(() => {
	const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
	if (!delta) return
	console.log(`mouse moved: ${delta.x}, ${delta.y}`)
})
```

Como `screenDelta` só contém o movimento de um único frame, leia-o sempre dentro de um [system](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md)para que nenhum movimento passe despercebido entre os frames.

{% hint style="warning" %}
**📔 Observação**: Evite referir-se ao `engine.RootEntity` no carregamento inicial da cena, porque isso pode resultar em erros se as entities ainda não estiverem inicializadas. Para evitar esse problema, refira-se sempre à entity dentro de um system. Ela estará sempre disponível, porque a primeira execução do system acontece quando a cena já foi inicializada corretamente.
{% endhint %}

{% hint style="warning" %}
**📔 Observação**: O que é descrito neste documento é relevante apenas para jogadores no desktop. No [aplicativo móvel](/creator/content-creator-pt/criar-para-mobile/cliente-movel/overview.md), a entrada é baseada em toque e não há um cursor que se mova livremente, então `screenDelta` sempre informa 0. Veja [Input no mobile](/creator/content-creator-pt/criar-para-mobile/desenvolver/input-on-mobile.md) para saber como a entrada funciona em dispositivos com toque, e [Detect platform](/creator/content-creator-pt/criar-para-mobile/desenvolver/detect-platform.md) para oferecer controles alternativos aos jogadores no mobile.
{% endhint %}

## Movimento do mouse enquanto o cursor está bloqueado

`screenDelta` comporta-se de forma diferente das outras propriedades de `PrimaryPointerInfo` quando o cursor está [bloqueado](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#lock-or-unlock-the-cursor): `screenCoordinates` fica congelado no centro da tela e `worldRayDirection` sempre informa o raio no centro da tela, mas `screenDelta` continua informando o movimento bruto do mouse em cada frame. Isso faz dela a única forma de ler o movimento do mouse enquanto o cursor está bloqueado, o que é exatamente o que você precisa para controles personalizados de câmera ou mira.

## Arraste para girar um objeto

O exemplo a seguir permite que o jogador gire um cubo arrastando o mouse lateralmente enquanto mantém o botão do ponteiro pressionado:

```ts
import {
	engine,
	InputAction,
	inputSystem,
	MeshCollider,
	MeshRenderer,
	PrimaryPointerInfo,
	Transform,
} from '@dcl/sdk/ecs'
import { Quaternion, Vector3 } from '@dcl/sdk/math'

const DRAG_SENSITIVITY = 0.5

export function main() {
	const cube = engine.addEntity()
	Transform.create(cube, { position: Vector3.create(8, 1, 8) })
	MeshRenderer.setBox(cube)
	MeshCollider.setBox(cube)

	engine.addSystem(() => {
		// girar apenas enquanto o botão do ponteiro estiver pressionado
		if (!inputSystem.isPressed(InputAction.IA_POINTER)) return

		const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
		if (!delta || delta.x === 0) return

		const transform = Transform.getMutable(cube)
		transform.rotation = Quaternion.multiply(
			transform.rotation,
			Quaternion.fromEulerDegrees(0, delta.x * DRAG_SENSITIVITY, 0)
		)
	})
}
```

O mesmo padrão funciona para qualquer interação de arrastar: deslize uma entity ao longo de um trilho usando `delta.x` como deslocamento, percorra uma animação ou detecte um swipe rápido verificando valores altos de delta.

## Controles de câmera em mouselook

Como `screenDelta` continua funcionando enquanto o cursor está bloqueado, você pode usá-lo para criar controles de mouselook para uma [virtual camera](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/camera.md#using-virtual-cameras). Para fazer isso, acumule o movimento do mouse em ângulos de yaw e pitch e depois aplique-os à rotação da câmera em cada frame.

No exemplo a seguir, o jogador clica em uma caixa para mudar para uma virtual camera que ele pode controlar com o mouse e pressiona o botão secundário (*F* ou clique com o botão direito) para voltar à câmera padrão. Enquanto a virtual camera está ativa, a cena também bloqueia o cursor e congela o avatar com um [input modifier](/creator/content-creator-pt/scenes-sdk7/interatividade/avatares/locomotion.md#freeze-the-player), para que o jogador não ande sem rumo enquanto controla a câmera.

```ts
import {
	engine,
	Entity,
	InputAction,
	InputModifier,
	inputSystem,
	MainCamera,
	MeshCollider,
	MeshRenderer,
	PointerEventType,
	pointerEventsSystem,
	PointerLock,
	PrimaryPointerInfo,
	Transform,
	VirtualCamera,
} from '@dcl/sdk/ecs'
import { Quaternion, Vector3 } from '@dcl/sdk/math'

// graus de rotação da câmera por pixel de movimento do mouse
const SENSITIVITY = 0.15

let cameraEntity: Entity
let cameraActive = false
let yaw = 0
let pitch = 0

export function main() {
	// a entity que a câmera segue
	cameraEntity = engine.addEntity()
	Transform.create(cameraEntity, { position: Vector3.create(8, 3, 8) })
	VirtualCamera.create(cameraEntity, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(0.5) },
	})

	// clique nesta caixa para entrar no modo mouselook
	const box = engine.addEntity()
	Transform.create(box, { position: Vector3.create(8, 1, 4) })
	MeshRenderer.setBox(box)
	MeshCollider.setBox(box)
	pointerEventsSystem.onPointerDown(
		{
			entity: box,
			opts: { button: InputAction.IA_POINTER, hoverText: 'Controlar câmera' },
		},
		() => activateCamera(true)
	)

	// controlar a câmera com o mouse
	engine.addSystem(() => {
		if (!cameraActive) return
		if (!PointerLock.getOrNull(engine.CameraEntity)?.isPointerLocked) return

		const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
		if (!delta) return

		yaw += delta.x * SENSITIVITY
		// limitar o pitch para que a câmera não vire
		pitch = Math.max(-85, Math.min(85, pitch + delta.y * SENSITIVITY))

		Transform.getMutable(cameraEntity).rotation = Quaternion.fromEulerDegrees(pitch, yaw, 0)
	})

	// sair do modo mouselook com o botão secundário
	engine.addSystem(() => {
		if (!cameraActive) return
		if (inputSystem.isTriggered(InputAction.IA_SECONDARY, PointerEventType.PET_DOWN)) {
			activateCamera(false)
		}
	})
}

function activateCamera(active: boolean) {
	cameraActive = active

	// atribuir ou liberar a virtual camera
	MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: active ? cameraEntity : undefined,
	})

	// congelar o avatar enquanto a câmera está sendo controlada
	InputModifier.createOrReplace(engine.PlayerEntity, {
		mode: InputModifier.Mode.Standard({ disableAll: active }),
	})

	// bloquear o cursor, para que o mouse controle a câmera imediatamente
	PointerLock.createOrReplace(engine.CameraEntity, { isPointerLocked: active })
}
```

Algumas coisas a observar neste exemplo:

* O system adiciona `delta.y` ao pitch. Mover o mouse para cima informa um `delta.y`, o que reduz o pitch e inclina a câmera para cima. Inverta esse sinal se você preferir controles verticais invertidos.
* O pitch é limitado a um intervalo de -85 a 85 graus, então a câmera nunca pode virar para trás.
* O `SENSITIVITY` a constante expressa graus de rotação por pixel de movimento do mouse; ajuste-a ao seu gosto.

{% hint style="info" %}
**💡 Dica**: O jogador pode desbloquear o cursor a qualquer momento pressionando *Esc* ou clicando com o botão direito, o que faz a câmera parar de responder ao mouse. Sempre ofereça aos jogadores uma forma clara de sair totalmente do modo de câmera, como o botão secundário no exemplo acima. Você também pode bloquear o cursor novamente pelo código, veja [Bloquear ou desbloquear o cursor](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md#lock-or-unlock-the-cursor).
{% endhint %}

## Tópicos relacionados

Para ler a posição absoluta do cursor na tela em vez do seu movimento, use a `screenCoordinates` propriedade do mesmo componente. Veja [Verifique a posição do cursor do jogador](/creator/content-creator-pt/scenes-sdk7/interatividade/user-data.md#check-the-players-cursor-position).

Para descobrir qual entity está sob o cursor, combine a `worldRayDirection` propriedade com um raycast. Veja [Raycasting](/creator/content-creator-pt/scenes-sdk7/interatividade/raycasting.md).

{% hint style="info" %}
**💡 Dica**: Para exemplos práticos do estado do ponteiro, veja a [`0,5-primary-cursor-info`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,5-primary-cursor-info) cena de teste, que lê `PrimaryPointerInfo` a cada frame e alimenta `worldRayDirection` em um raycast; [`31,20-pointer-lock-control`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/31,20-pointer-lock-control), que solicita e libera a captura do cursor escrevendo `PointerLock.isPointerLocked`; e [`32,20-virtual-camera-mouse-look`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/32,20-virtual-camera-mouse-look), que mostra `screenDelta` ainda informando movimento enquanto `screenCoordinates` fica congelado no centro da tela durante o bloqueio.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/mouse-movement.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
