Skip to content

UNRaf-PROGRAMACION/input-system-gamepad-unraf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

InputSystem - Sistema de Entrada Unificado para Phaser

Un sistema de entrada flexible y configurable para Phaser 3 que proporciona compatibilidad con teclado y gamepad arcade Unraf (USB GENERIC).

🎮 Características

  • Mapeo configurable de teclas de teclado
  • Compatibilidad fija con gamepad arcade Unraf
  • Detección simultánea de entrada de teclado y gamepad
  • Métodos para detectar pulsaciones continuas y momentáneas
  • Constantes predefinidas para evitar hardcodear strings
  • API simple y consistente para cualquier tipo de juego

📋 Especificaciones del Gamepad Unraf

El gamepad arcade Unraf es reconocido por el sistema como USB GENERIC y cuenta con:

Botones (4 únicos):

  • Norte (B3) - Botón superior
  • Este (B1) - Botón derecho
  • Sur (B0) - Botón inferior
  • Oeste (B2) - Botón izquierdo

Joystick (1 único):

  • Eje X (axis 0): Valores de -1 (izquierda) a 1 (derecha)
  • Eje Y (axis 1): Valores de -1 (arriba) a 1 (abajo)

Comandos Disponibles para ejecucion del proyecto

Comando Descripción
npm install Instala las dependencias del proyecto
npm run dev Inicia un servidor web de desarrollo
npm run build Crea una compilación de producción en la carpeta dist
npm run dev-nolog Inicia un servidor web de desarrollo sin enviar datos anónimos (ver "Sobre log.js" abajo)
npm run build-nolog Crea una compilación de producción en la carpeta dist sin enviar datos anónimos (ver "Sobre log.js" abajo)

🚀 Instalación Rápida

import InputSystem, { INPUT_ACTIONS } from "./utils/InputSystem.js";

// En tu escena de Phaser
export class GameScene extends Scene {
  create() {
    // Inicializar el sistema de entrada
    this.inputSystem = new InputSystem(this.input);
    
    // Configurar controles de teclado
    this.inputSystem.configureKeyboard({
      [INPUT_ACTIONS.NORTH]: [Phaser.Input.Keyboard.KeyCodes.SPACE],
      [INPUT_ACTIONS.SOUTH]: [Phaser.Input.Keyboard.KeyCodes.X],
      [INPUT_ACTIONS.EAST]: [Phaser.Input.Keyboard.KeyCodes.D],
      [INPUT_ACTIONS.WEST]: [Phaser.Input.Keyboard.KeyCodes.A]
    });
  }
  
  update() {
    // Verificar entrada
    if (this.inputSystem.isPressed(INPUT_ACTIONS.NORTH)) {
      // Acción continua
      this.player.jump();
    }
    
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.SOUTH)) {
      // Acción única por pulsación
      this.openMenu();
    }
  }
}

📚 Constantes Disponibles

import { INPUT_ACTIONS } from "./utils/InputSystem.js";

// Movimientos direccionales
INPUT_ACTIONS.UP     // Movimiento hacia arriba (eje Y negativo)
INPUT_ACTIONS.DOWN   // Movimiento hacia abajo (eje Y positivo)
INPUT_ACTIONS.LEFT   // Movimiento hacia la izquierda (eje X negativo)
INPUT_ACTIONS.RIGHT  // Movimiento hacia la derecha (eje X positivo)

// Botones del gamepad
INPUT_ACTIONS.NORTH  // Botón norte (B3)
INPUT_ACTIONS.EAST   // Botón este (B1)
INPUT_ACTIONS.SOUTH  // Botón sur (B0)
INPUT_ACTIONS.WEST   // Botón oeste (B2)

🎯 Ejemplos de Uso

Ejemplo 1: Movimiento de Personaje

export class GameScene extends Scene {
  create() {
    this.inputSystem = new InputSystem(this.input);
    
    // Configurar controles WASD + flechas
    this.inputSystem.configureKeyboard({
      [INPUT_ACTIONS.UP]: [Phaser.Input.Keyboard.KeyCodes.W, Phaser.Input.Keyboard.KeyCodes.UP],
      [INPUT_ACTIONS.DOWN]: [Phaser.Input.Keyboard.KeyCodes.S, Phaser.Input.Keyboard.KeyCodes.DOWN],
      [INPUT_ACTIONS.LEFT]: [Phaser.Input.Keyboard.KeyCodes.A, Phaser.Input.Keyboard.KeyCodes.LEFT],
      [INPUT_ACTIONS.RIGHT]: [Phaser.Input.Keyboard.KeyCodes.D, Phaser.Input.Keyboard.KeyCodes.RIGHT]
    });
    
    this.player = this.add.sprite(400, 300, 'player');
    this.playerSpeed = 200;
  }
  
  update(time, delta) {
    const deltaTime = delta / 1000;
    let velocityX = 0;
    let velocityY = 0;
    
    // Movimiento horizontal
    if (this.inputSystem.isPressed(INPUT_ACTIONS.LEFT)) {
      velocityX = -this.playerSpeed;
    } else if (this.inputSystem.isPressed(INPUT_ACTIONS.RIGHT)) {
      velocityX = this.playerSpeed;
    }
    
    // Movimiento vertical
    if (this.inputSystem.isPressed(INPUT_ACTIONS.UP)) {
      velocityY = -this.playerSpeed;
    } else if (this.inputSystem.isPressed(INPUT_ACTIONS.DOWN)) {
      velocityY = this.playerSpeed;
    }
    
    // Aplicar movimiento
    this.player.x += velocityX * deltaTime;
    this.player.y += velocityY * deltaTime;
  }
}

Ejemplo 2: Menú Navegable

export class MenuScene extends Scene {
  create() {
    this.inputSystem = new InputSystem(this.input);
    
    // Configurar navegación de menú
    this.inputSystem.configureKeyboardByString({
      [INPUT_ACTIONS.UP]: ['W', 'UP'],
      [INPUT_ACTIONS.DOWN]: ['S', 'DOWN'],
      [INPUT_ACTIONS.NORTH]: ['ENTER', 'SPACE'], // Confirmar
      [INPUT_ACTIONS.SOUTH]: ['ESC', 'X']        // Cancelar
    });
    
    this.menuItems = ['Nuevo Juego', 'Cargar', 'Opciones', 'Salir'];
    this.selectedIndex = 0;
  }
  
  update() {
    // Navegación del menú (solo una vez por pulsación)
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.UP)) {
      this.selectedIndex = Math.max(0, this.selectedIndex - 1);
      this.updateMenuDisplay();
    }
    
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.DOWN)) {
      this.selectedIndex = Math.min(this.menuItems.length - 1, this.selectedIndex + 1);
      this.updateMenuDisplay();
    }
    
    // Confirmar selección
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.NORTH)) {
      this.selectMenuItem(this.selectedIndex);
    }
    
    // Cancelar/Volver
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.SOUTH)) {
      this.goBack();
    }
  }
}

Ejemplo 3: Juego de Plataformas

export class PlatformerScene extends Scene {
  create() {
    this.inputSystem = new InputSystem(this.input);
    
    // Controles típicos de plataformero
    this.inputSystem.configureKeyboard({
      [INPUT_ACTIONS.LEFT]: [Phaser.Input.Keyboard.KeyCodes.A, Phaser.Input.Keyboard.KeyCodes.LEFT],
      [INPUT_ACTIONS.RIGHT]: [Phaser.Input.Keyboard.KeyCodes.D, Phaser.Input.Keyboard.KeyCodes.RIGHT],
      [INPUT_ACTIONS.NORTH]: [Phaser.Input.Keyboard.KeyCodes.SPACE], // Saltar
      [INPUT_ACTIONS.SOUTH]: [Phaser.Input.Keyboard.KeyCodes.S],     // Agacharse
      [INPUT_ACTIONS.EAST]: [Phaser.Input.Keyboard.KeyCodes.E],      // Interactuar
      [INPUT_ACTIONS.WEST]: [Phaser.Input.Keyboard.KeyCodes.Q]       // Habilidad especial
    });
  }
  
  update() {
    // Movimiento horizontal continuo
    if (this.inputSystem.isPressed(INPUT_ACTIONS.LEFT)) {
      this.player.setVelocityX(-200);
      this.player.flipX = true;
    } else if (this.inputSystem.isPressed(INPUT_ACTIONS.RIGHT)) {
      this.player.setVelocityX(200);
      this.player.flipX = false;
    } else {
      this.player.setVelocityX(0);
    }
    
    // Salto (una sola vez por pulsación)
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.NORTH) && this.player.body.onFloor()) {
      this.player.setVelocityY(-500);
    }
    
    // Agacharse (continuo)
    if (this.inputSystem.isPressed(INPUT_ACTIONS.SOUTH)) {
      this.player.body.setSize(32, 16); // Hitbox más pequeña
    } else {
      this.player.body.setSize(32, 32); // Hitbox normal
    }
    
    // Interacciones (una vez por pulsación)
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.EAST)) {
      this.interactWithNearbyObjects();
    }
    
    if (this.inputSystem.isJustPressed(INPUT_ACTIONS.WEST)) {
      this.useSpecialAbility();
    }
  }
}

Ejemplo 4: Configuraciones Personalizadas

// Configuración para jugadores zurdos
inputSystem.configureKeyboard({
  [INPUT_ACTIONS.UP]: [Phaser.Input.Keyboard.KeyCodes.UP],
  [INPUT_ACTIONS.DOWN]: [Phaser.Input.Keyboard.KeyCodes.DOWN],
  [INPUT_ACTIONS.LEFT]: [Phaser.Input.Keyboard.KeyCodes.LEFT],
  [INPUT_ACTIONS.RIGHT]: [Phaser.Input.Keyboard.KeyCodes.RIGHT],
  [INPUT_ACTIONS.NORTH]: [Phaser.Input.Keyboard.KeyCodes.NUMPAD_ZERO],
  [INPUT_ACTIONS.SOUTH]: [Phaser.Input.Keyboard.KeyCodes.NUMPAD_ONE]
});

// Configuración estilo FPS
inputSystem.configureKeyboardByString({
  [INPUT_ACTIONS.UP]: ['W'],
  [INPUT_ACTIONS.DOWN]: ['S'],
  [INPUT_ACTIONS.LEFT]: ['A'],
  [INPUT_ACTIONS.RIGHT]: ['D'],
  [INPUT_ACTIONS.NORTH]: ['SPACE'],    // Saltar
  [INPUT_ACTIONS.SOUTH]: ['C'],        // Agacharse
  [INPUT_ACTIONS.EAST]: ['E'],         // Usar/Interactuar
  [INPUT_ACTIONS.WEST]: ['Q']          // Habilidad
});

// Configuración para arcade clásico
inputSystem.configureKeyboardByString({
  [INPUT_ACTIONS.NORTH]: ['Z'],
  [INPUT_ACTIONS.SOUTH]: ['X'],
  [INPUT_ACTIONS.EAST]: ['C'],
  [INPUT_ACTIONS.WEST]: ['V']
});

🛠️ API Completa

Métodos Principales

isPressed(action: string): boolean

Verifica si una acción está siendo presionada actualmente (continua).

if (inputSystem.isPressed(INPUT_ACTIONS.NORTH)) {
  // Se ejecuta mientras el botón esté presionado
}

isJustPressed(action: string): boolean

Verifica si una acción fue presionada en este frame específico (momentánea).

if (inputSystem.isJustPressed(INPUT_ACTIONS.NORTH)) {
  // Se ejecuta solo una vez por pulsación
}

Métodos de Configuración

configureKeyboard(mappings: Object)

Configura controles de teclado usando KeyCodes de Phaser.

inputSystem.configureKeyboard({
  [INPUT_ACTIONS.NORTH]: [Phaser.Input.Keyboard.KeyCodes.SPACE]
});

configureKeyboardByString(mappings: Object)

Configura controles de teclado usando strings (más fácil).

inputSystem.configureKeyboardByString({
  [INPUT_ACTIONS.NORTH]: ['SPACE', 'ENTER']
});

setMapping(action: string, config: Object)

Configura un mapeo individual.

inputSystem.setMapping(INPUT_ACTIONS.NORTH, {
  keyboard: [Phaser.Input.Keyboard.KeyCodes.SPACE]
});

Métodos de Información

getMapping(): Object

Obtiene la configuración completa actual.

getKeyboardMapping(action: string): Array

Obtiene las teclas asignadas a una acción específica.

getAllKeyboardMappings(): Object

Obtiene todos los mapeos de teclado actuales.

🎮 Compatibilidad con Gamepad

El InputSystem maneja automáticamente el gamepad Unraf cuando se conecta. Los controles de gamepad son fijos y no requieren configuración:

  • Joystick: Mapea automáticamente a UP, DOWN, LEFT, RIGHT
  • Botones: Mapea automáticamente a NORTH, EAST, SOUTH, WEST
// No necesitas configurar nada para gamepad
// Funciona automáticamente cuando se conecta
this.inputSystem = new InputSystem(this.input);

// Ambos funcionarán simultáneamente:
// - Teclado: teclas configuradas por ti
// - Gamepad: mapeo fijo del arcade Unraf

🔧 Casos de Uso Avanzados

Pantalla de Configuración de Controles

export class ControlsScene extends Scene {
  create() {
    this.inputSystem = new InputSystem(this.input);
    
    // Mostrar controles actuales
    const currentMappings = this.inputSystem.getAllKeyboardMappings();
    Object.keys(currentMappings).forEach(action => {
      const keys = currentMappings[action];
      console.log(`${action}: ${keys.join(', ')}`);
    });
  }
  
  // Permitir al usuario cambiar controles
  remapControl(action, newKeys) {
    this.inputSystem.configureKeyboard({
      [action]: newKeys
    });
  }
}

Detección de Dispositivo de Entrada

update() {
  // Verificar qué dispositivo se está usando
  if (this.inputSystem.isKeyboardPressed(INPUT_ACTIONS.NORTH)) {
    this.showKeyboardPrompts();
  } else if (this.inputSystem.isGamepadPressed(INPUT_ACTIONS.NORTH)) {
    this.showGamepadPrompts();
  }
}

📝 Notas Importantes

  1. Gamepad fijo: Los controles de gamepad no deben modificarse para mantener compatibilidad con Unraf
  2. Teclado configurable: Solo los controles de teclado son configurables por el desarrollador
  3. Inicialización: Siempre inicializa el InputSystem en el método create() de tu escena
  4. Constantes: Usa siempre INPUT_ACTIONS en lugar de strings hardcodeados
  5. Performance: Los métodos isPressed() e isJustPressed() son optimizados para uso en update()

🤝 Contribución

Para contribuir al desarrollo del InputSystem:

  1. Fork el repositorio
  2. Crea una rama para tu feature
  3. Mantén la compatibilidad con gamepad Unraf
  4. Actualiza la documentación

📄 Licencia

Este proyecto está bajo la licencia MIT. Ver archivo LICENSE para más detalles.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors