Skip to main content

Cómo añadir un cursor personalizado

Este tutorial fue escrito en febrero de 2026, para la v2 del motor.

La mayoría de los juegos se ven mejor con un cursor personalizado. La flecha predeterminada del navegador grita "página web" — rompe toda la estética pixel-art. Cambiarla por tu propio sprite es rápido y marca una gran diferencia.

Necesitamos tres cosas: ocultar el cursor predeterminado, definir un sprite de cursor y dibujarlo en la posición del ratón en cada frame.

Ocultar el cursor predeterminado

Llama a cursor(false) en tu función init() para ocultar el cursor del navegador. Internamente, establece cursor: none en el CSS del canvas.

// inside init()
cursor(false);

// the browser cursor is now hidden over the canvas
// call cursor() to restore it, or cursor('pointer') for a CSS cursor
Custom Cursor: Hide Cursor
Mueve el ratón sobre el canvas — el cursor predeterminado desaparece

Puedes restaurarlo en cualquier momento — cursor() devuelve la flecha predeterminada, y cursor('pointer') o cualquier otro valor CSS de cursor también funciona. Útil si tu juego tiene menús que se sienten mejor con un cursor normal.

Definir un sprite de cursor

Los sprites en Floaty son arrays de 8x8 valores de color. Cada número corresponde a un color de la paleta (0–15), y -1 significa transparente. Aquí hay un cursor de flecha — 7 (blanco) rellena la forma, 0 (negro) la delinea:

const sprites = {
    cursor: [
         7,  0, -1, -1, -1, -1, -1, -1,
         7,  7,  0, -1, -1, -1, -1, -1,
         7,  7,  7,  0, -1, -1, -1, -1,
         7,  7,  7,  7,  0, -1, -1, -1,
         7,  7,  7,  7,  7,  0, -1, -1,
         7,  7,  0,  0,  0,  0, -1, -1,
         7,  0,  0, -1, -1, -1, -1, -1,
         0,  0, -1, -1, -1, -1, -1, -1,
    ],
};
Custom Cursor: Define Sprite
El sprite de cursor flecha renderizado desde sus datos de píxeles en el centro de la pantalla

Lee el array de arriba a abajo, de izquierda a derecha, y verás cómo la flecha toma forma: un solo píxel en la esquina superior izquierda, ensanchándose fila por fila, y luego estrechándose. Pasamos el objeto sprites a start() para que el motor lo conozca.

Consejo: Puedes diseñar sprites visualmente en el editor de sprites — dibuja tu cursor píxel a píxel, luego copia el array con Ctrl+C (o Cmd+C en Mac).

Dibujar el cursor

Solo queda dibujarlo. Llama a mouse() para obtener la posición actual como { x, y }, luego spr() para dibujar el sprite ahí:

engine.scope(({ start, cls, spr, mouse, cursor }) => {
    const sprites = {
        cursor: [
             7,  0, -1, -1, -1, -1, -1, -1,
             7,  7,  0, -1, -1, -1, -1, -1,
             7,  7,  7,  0, -1, -1, -1, -1,
             7,  7,  7,  7,  0, -1, -1, -1,
             7,  7,  7,  7,  7,  0, -1, -1,
             7,  7,  0,  0,  0,  0, -1, -1,
             7,  0,  0, -1, -1, -1, -1, -1,
             0,  0, -1, -1, -1, -1, -1, -1,
        ],
    };

    function init() {
        cursor(false);
    }

    function draw() {
        cls(12);
        const pos = mouse();
        spr('cursor', pos.x, pos.y);
    }

    start({ sprites, sounds: {}, init, draw, target });
});
Custom Cursor: Draw Cursor
Mueve el ratón para ver el cursor flecha personalizado seguirlo

El motor convierte las coordenadas de pantalla a coordenadas del canvas por ti, así que mouse() devuelve valores en el mismo espacio de 128x128 píxeles en el que dibujas. La esquina superior izquierda del sprite cae en la posición del ratón — se siente natural para una flecha ya que la "punta" está arriba a la izquierda.

Para ir más allá

No todas las formas de cursor funcionan con alineación arriba-izquierda. Una cruceta debería estar centrada en la posición del ratón — resta la mitad del tamaño del sprite de cada coordenada:

const sprites = {
    crosshair: [
        -1, -1, -1,  7, -1, -1, -1, -1,
        -1, -1, -1,  7, -1, -1, -1, -1,
        -1, -1, -1,  7, -1, -1, -1, -1,
         7,  7,  7, -1,  7,  7,  7, -1,
        -1, -1, -1,  7, -1, -1, -1, -1,
        -1, -1, -1,  7, -1, -1, -1, -1,
        -1, -1, -1,  7, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1,
    ],
};

// in draw(), center the crosshair on the mouse position:
const pos = mouse();
spr('crosshair', pos.x - 3, pos.y - 3);
Custom Cursor: Crosshair
Mueve el ratón — la cruceta está centrada en la posición del ratón en lugar de alineada arriba a la izquierda

Algunas direcciones que podrías tomar:

  • Cursores animados — define múltiples frames de sprite y alterna entre ellos con un contador
  • Cursores sensibles al contexto — cambia el sprite según sobre qué se encuentra el ratón (una mano para botones, una cruceta al apuntar)
  • Estelas de cursor — almacena las últimas posiciones del ratón en un array y dibuja copias desvanecidas del sprite en cada una