4x Animals
Un 4X de estrategia por turnos hecho para el móvil: civilizaciones de animales que exploran, expanden, explotan y exterminan, en sesiones que entran en un bolsillo.
- Rust
- wgpu
- WGSL
- WASM
- WebGPU
- Tauri
- winit
- JNI
4X Animals es un juego de estrategia por turnos del género 4X (eXplore, eXpand, eXploit, eXterminate) pensado de raíz para mobile. El jugador toma una civilización de animales y la lleva de una manada que explora el mapa a un imperio que domina el continente, en partidas diseñadas para jugarse en el celular sin perder profundidad. La ambición del proyecto es llegar a miles de jugadores en su lanzamiento. Lo que permite apuntar tan alto es un motor 3D propio en Rust/wgpu —una sola simulación que corre nativa en Android, web y desktop— y un equipo que Miguel lidera y dirige, del diseño de producto al renderer de bajo nivel.
Mil jugadores
meta de lanzamiento, no dato logrado
Ejes de juego
explore · expand · exploit · exterminate
Plataformas
Android · web · desktop
LOC Rust
motor propio · ~8k TS además
Un 4X que normalmente vive en la PC, llevado al bolsillo
El 4X es uno de los géneros más profundos de la estrategia, pero casi siempre vive en sesiones largas frente a un escritorio. 4X Animals busca traer esa profundidad —explorar el mapa, expandir tu civilización, explotar recursos y exterminar rivales— a partidas que entren en el ritmo del móvil, sin sentirse recortado. Y para apuntar a miles de jugadores en el lanzamiento, tiene que correr bien en teléfonos reales, no solo en hardware de gama alta.
Motor propio para no quedar atado a un engine pesado
En lugar de cargar un motor genérico, el equipo construye su propio renderer sobre wgpu (que compila a Vulkan, Metal, DX y WebGPU), con una arquitectura de una sola simulación y skins delgadas por plataforma. Eso permite que el mismo juego corra nativo en Android, navegador y escritorio, controlar el costo en mobile y mover el proyecto hacia su meta de alcance con un equipo chico y dirigido. Miguel lidera tanto la dirección del producto como el corazón técnico del motor.
Un juego upcoming con base técnica para escalar
4X Animals está en desarrollo activo: ya corre lado a lado en Android, browser y desktop sobre una simulación determinista y testeada, lista para sostener el multijugador competitivo. El objetivo declarado es llegar a más de diez mil jugadores en su lanzamiento; el motor propio y la arquitectura cross-platform son la apuesta que hace creíble ese número.
Lo que se ve
Tri-plataforma lado a lado
El mismo 4X corriendo a la par en Android, navegador y desktop desde un único core en Rust/wgpu.
Las 4 X del género
Explorar, expandir, explotar y exterminar con civilizaciones de animales: el mapa hexagonal se revela mientras la manada avanza.
Creación de Rey
Pantalla de fundación de civilización con paleta oro sobre azul-noche, el momento de identidad de cada partida.
Mapa hexagonal en 3D
Tablero de hexágonos con relieve, niebla de guerra y unidades animadas, renderizado por el motor propio.
Panel de turno
La UI condensa producción, exploración y combate en gestos pensados para el pulgar, sin perder la profundidad del 4X.
Shaders WGSL a mano
Iluminación, niebla y agua escritas en WGSL crudo para correr igual en Vulkan, Metal, DX y WebGPU.
Combate por turnos
Resolución de batallas con la animación y el feedback de daño calculados por la simulación determinista.
Lo que no se ve
La contraparte invisible de la pantalla: la arquitectura, el backend y la infraestructura que sostienen el producto.
Motor 3D propio sobre wgpu
Un renderer escrito desde cero sobre wgpu que compila a Vulkan, Metal, DX12 y WebGPU, con shaders WGSL a mano. Una sola simulación y skins delgadas por plataforma: nada de un engine genérico pesado.
Simulación determinista server-authoritative
El estado del juego avanza por un motor de turnos determinista: dadas las mismas entradas y semilla, el resultado es idéntico en todo dispositivo. Es la base sobre la que se monta el multijugador competitivo y el anti-cheat.
Sincronización de estado por deltas
En vez de mandar el mundo entero, el servidor difunde deltas comprimidos del estado por turno; el cliente reconcilia contra su predicción local. Clave para que el móvil aguante con poco ancho de banda.
Matchmaking móvil por habilidad
Cola de emparejamiento que agrupa por rating y región, con expansión progresiva del rango para no dejar a nadie esperando. Pensada para sostener miles de jugadores concurrentes en el lanzamiento.
Bridge nativo Android por JNI
El core en Rust se expone a Android vía JNI y al navegador vía WASM/WebGPU desde la misma fuente. El bucle de juego corre nativo en cada plataforma sin reescribir la lógica.
Replays y validación anti-cheat
Como la simulación es determinista, cada partida se guarda como secuencia de entradas y se puede re-ejecutar en el servidor para detectar estados imposibles o clientes manipulados.
Las piezas que lo sostienen
Código real del proyecto — los fragmentos que sostienen la idea, tal cual viven en el repositorio.
fn smoothstep(edge0: f32, edge1: f32, t: f32) -> f32 {
let x = ((t - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
x * x * (3.0 - 2.0 * x)
}
/// Hornea un splatmap 64x64: 0 = material-A puro, 255 = material-B puro.
fn bake_splatmap(mask: NeighborMask) -> Vec<u8> {
let size = SPLATMAP_SIZE as usize;
let mut pixels = vec![0u8; size * size];
for pv in 0..size {
for pu in 0..size {
let u = (pu as f32 + 0.5) / size as f32;
let v = (pv as f32 + 0.5) / size as f32;
let mut blend = 0.0_f32;
if mask.north { blend = blend.max(smoothstep(0.55, 0.85, v)); }
if mask.south { blend = blend.max(smoothstep(0.45, 0.15, v)); }
if mask.east { blend = blend.max(smoothstep(0.55, 0.85, u)); }
if mask.west { blend = blend.max(smoothstep(0.45, 0.15, u)); }
pixels[pv * size + pu] = (blend * 255.0) as u8;
}
}
pixels
}Terrain blend por splatmap + smoothstep. Se prehornean las 16 combinaciones de NeighborMask al arrancar: un splatmap por patrón único, mezclado con smoothstep para bordes suaves.
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let uv_t = in.uv * 4.0; // tiling del material
let blend_t = smoothstep(0.3, 0.7,
textureSample(splatmap, splat_sampler, in.uv).r);
let alb = mix(
textureSample(albedo_a, sampler_a, uv_t).rgb,
textureSample(albedo_b, sampler_b, uv_t).rgb,
blend_t);
let ao = mix(
textureSample(ao_a, sampler_a, uv_t).r,
textureSample(ao_b, sampler_b, uv_t).r,
blend_t);
let nl = max(dot(in.world_normal, camera.light_direction), camera.ambient);
return vec4<f32>(alb * nl * ao, 1.0);
}Fragment WGSL: mezcla de dos materiales PBR por splatmap. El fragment de la pipeline wgpu lee el splatmap horneado en CPU y mezcla con smoothstep dos materiales (albedo + AO) muestreados con UVs tileadas, antes de aplicar lambert con la dirección de luz de la cámara.
/// Color por LCG sembrado por 'tick' -> determinista y reproducible.
fn pick_color(tick: u64) -> MeteoriteColor {
const A: u64 = 6_364_136_223_846_793_005; // multiplicador de Knuth
const C: u64 = 1_442_695_040_888_963_407;
const M: u64 = 10_000;
let hash = tick.wrapping_mul(A).wrapping_add(C);
let bucket = hash % M; // 0..9999
if bucket < 5_000 {
MeteoriteColor::Green // 50%
} else if bucket < 7_500 {
MeteoriteColor::Blue // 25%
} else if bucket < 9_500 {
MeteoriteColor::Red // 20%
} else {
MeteoriteColor::Gold // 5%
}
}Scheduler determinista: mismo tick, mismo color. El color del meteorito sale de un LCG sembrado por el tick (hash multiplicativo de Knuth), no de un RNG global: la misma secuencia de ticks produce siempre la misma distribución (Verde 50% / Azul 25% / Rojo 20% / Oro 5%). Clave para una simulación reproducible y verificable por el servidor.
En concreto
Un 4X completo —explorar, expandir, explotar, exterminar— condensado en sesiones pensadas para jugarse desde el teléfono.
Civilizaciones de animales con identidad propia: el gancho es un 4X accesible y con carácter, no un clon serio de los clásicos de PC.
Motor 3D propio en Rust/wgpu con shaders WGSL escritos a mano: corre nativo en Android (JNI), web (WASM/WebGPU) y desktop (winit) desde un solo core.
Simulación server-authoritative determinista, base sobre la que se construirá el multijugador competitivo.
Diseño de producto documentado a nivel estudio, con anti-referencias explícitas y un equipo dirigido para shippear, no solo prototipar.