Normalización Multiplataforma: Guía para Evitar Errores de Case Sensitivity

Normalización Multiplataforma: Guía para Evitar Errores de Case Sensitivity

✍️ Angelus

Uno de los bugs más insidiosos en desarrollo multiplataforma es la diferencia en cómo los sistemas operativos manejan mayúsculas en nombres de archivos. Esta guía documenta las convenciones y herramientas para evitarlo desde el principio.

El problema: Windows vs Linux/Android/Mac

Cuando desarrollas un juego o app que corre en múltiples plataformas, te encuentras con una diferencia fundamental en cómo los sistemas operativos tratan los nombres de archivos:

  • Windows: No es case-sensitive. Icon.png e icon.png son el mismo archivo.
  • Linux, Mac, Android, iOS: Sí son case-sensitive. Icon.png e icon.png son archivos distintos. Si tu código busca icon.png pero el archivo se llama Icon.png, no lo encuentra.

El resultado típico: el juego funciona perfectamente en tu máquina Windows, pero falla al sincronizarlo a Android o subirlo a un servidor Linux. El error es silencioso: imagen rota, icono que no aparece, pantalla de carga genérica. Sin mensaje de error claro.

La regla de oro: siempre minúsculas

La solución es adoptar una convención estricta y sin excepciones: todos los nombres de archivos en minúsculas. Funciona en Windows, Linux, Mac, Android e iOS.

❌ Incorrecto ✅ Correcto Razón
Icon.png icon.png Linux/Android lo necesita en minúsculas
MainBackground.webp main-background.webp Guiones son más legibles que camelCase en archivos
AudioMaster.js audio-master.js Consistencia: archivos siempre en kebab-case
GameData.JSON game-data.json Extensiones también en minúsculas
MY_CONFIG.txt my-config.txt Guiones, no underscores, para consistencia

En el código, las referencias a archivos también deben estar en minúsculas:

// Incorrecto — depende de si el archivo es Icon.png o icon.png
const icon = document.createElement("img");
icon.src = "images/Icon.png";

// Correcto — siempre minusculas
const icon2 = document.createElement("img");
icon2.src = "images/icon.png";

Estructura de carpetas estándar

Las carpetas también deben seguir la misma convención. Esta es la estructura recomendada para un proyecto web/app multiplataforma:

proyecto/
├── www/                          ← contenido web
│   ├── index.html
│   ├── assets/
│   │   ├── images/
│   │   │   ├── icon.png
│   │   │   ├── main-background.webp
│   │   │   └── ui-buttons.webp
│   │   ├── audio/
│   │   │   ├── theme-music.ogg
│   │   │   └── sfx-click.ogg
│   │   ├── css/
│   │   │   └── style.css
│   │   └── js/
│   │       ├── audio-master.js
│   │       └── app.js
│   └── data/
│       └── game-config.json
│
├── android/                      ← recursos específicos Android
│   └── res/
│       ├── mipmap-hdpi/
│       ├── mipmap-xhdpi/
│       └── mipmap-anydpi-v26/
│           └── ic-launcher.xml
│
└── docs/
    └── naming-conventions.md

Caso especial: iconos de aplicación en Android

Los iconos de Android son especialmente problemáticos porque requieren múltiples archivos en múltiples directorios con nombres muy específicos. La estructura correcta:

android/res/
├── mipmap-mdpi/
│   ├── ic-launcher.png           (192×192 px)
│   └── ic-launcher-foreground.png
├── mipmap-hdpi/
│   ├── ic-launcher.png           (288×288 px)
│   └── ic-launcher-foreground.png
├── mipmap-xhdpi/
│   ├── ic-launcher.png           (384×384 px)
│   └── ic-launcher-foreground.png
├── mipmap-xxhdpi/
│   ├── ic-launcher.png           (512×512 px)
│   └── ic-launcher-foreground.png
└── mipmap-anydpi-v26/
    └── ic-launcher.xml

El archivo ic-launcher.xml debe contener:

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@color/ic-launcher-background" />
    <foreground android:drawable="@mipmap/ic-launcher-foreground" />
</adaptive-icon>
Errores comunes con iconos Android

  • Olvidar copiar ic-launcher-foreground.png a TODOS los directorios mipmap-*
  • Nombrar el archivo ic_launcher.png (underscore) en lugar de ic-launcher.png (guión)
  • El XML referencia ic_launcher_foreground pero el archivo se llama ic-launcher-foreground.png
  • El archivo existe en mipmap-mdpi pero no en mipmap-hdpi (Android busca en la densidad apropiada)

Rutas en código: relativas y separadores

Otro problema de compatibilidad es el separador de ruta. En web y Linux se usa /; en Windows se usa \. En código JavaScript para web, siempre usa forward slash:

// Correcto — forward slash siempre en web
const imagePath = "assets/images/icon.png";
const audioPath = "assets/audio/theme-music.ogg";

// Incorrecto — backslash de Windows no funciona en URLs
// const imagePath = "assets\images\icon.png"; // Falla en navegador

// En RPG Maker, las rutas internas se normalizan automaticamente
ImageManager.loadBitmap("img/pictures/", "my-background");

Sincronización con Capacitor/Android

Si usas Capacitor para compilar tu app web a Android, hay problemas adicionales. Cuando ejecutas capacitor sync, algunos archivos pueden no copiarse si:

  • Están en .gitignore (Capacitor no los ve)
  • No están dentro de la carpeta www/
  • El nombre cambió de mayúsculas a minúsculas y git no detectó el cambio

Script de verificación post-sincronización:

#!/bin/bash
# verify-sync.sh

files_to_check=(
  "android/app/src/main/assets/www/index.html"
  "android/app/src/main/assets/www/assets/images/icon.png"
  "android/res/mipmap-hdpi/ic-launcher.png"
  "android/res/mipmap-hdpi/ic-launcher-foreground.png"
  "android/res/mipmap-xhdpi/ic-launcher.png"
  "android/res/mipmap-xhdpi/ic-launcher-foreground.png"
)

for file in "${files_to_check[@]}"; do
  if [ -f "$file" ]; then
    echo "✅ $file"
  else
    echo "❌ FALTA: $file"
  fi
done

Convenciones de nomenclatura completas

Tipo Convención Ejemplo
Variables JS camelCase playerHealth, mainBackground
Constantes JS UPPER_SNAKE_CASE CARD_WIDTH, MAX_PLAYERS
Clases JS PascalCase GameState, AudioMaster
Archivos de código kebab-case audio-master.js, game-state.js
Imágenes kebab-case main-background.png, ui-button.webp
Audio kebab-case theme-music.ogg, sfx-click.ogg

La regla simple: camelCase para código, kebab-case para archivos. Nunca mezcles.

Checklist de verificación antes de publicar

  • Todos los nombres de archivos en minúsculas
  • Guiones en lugar de underscores o camelCase en nombres de archivo
  • Todas las referencias en código coinciden exactamente con los nombres de archivo
  • En Android, iconos presentes en todos los directorios mipmap-*
  • El XML de Android referencia correctamente los iconos
  • Rutas en código usan forward slash /, nunca backslash \
  • Después de sincronizar, ejecutar el script de verificación
  • Probar en al menos un navegador web y una plataforma móvil

La normalización multiplataforma no es glamurosa, pero es el tipo de decisión que evita horas de debugging frustrante. Invertir 30 minutos al inicio del proyecto en establecer estas convenciones ahorra 10 horas más tarde.

Regla final: Cuando dudes, usa minúsculas y guiones. Nunca falla.

Compartir:
|
← Anterior
Cómo Crear un Minijuego de Cartas en RPG Maker
Siguiente →
¿Cómo Hacer un Videojuego en RPG Maker Guía Completa Paso a Paso
Inicio Blog Normalización Multiplataforma: Guía para Evitar Errores de Case Sensitivity
← Volver al Blog