Three.jsGLSLGameIncrementalBrowser GameSpaceIndie

STELLAR EPOCH: APHELION — Un juego espacial incremental gratuito para navegador

Sloth255
Sloth255
·5 min read·1,092 words

Género: Espacio / Juego incremental
Plataforma: Navegador (Móvil & PC)
Precio: Gratis — sin necesidad de cuenta
URL: https://stellar-epoch.sloth255.com/


Descripción del juego

STELLAR EPOCH: APHELION es un juego incremental de temática espacial que se ejecuta completamente en tu navegador. Sin aplicación que instalar, sin suscripción, sin muros de pago. Ya sea en un smartphone o en un escritorio, todo lo que necesitas es un navegador para empezar a jugar de inmediato.

El título Aphelion hace referencia al punto en la órbita de un planeta donde está más alejado del Sol — un término astronómico que captura la vasta y romántica escala del universo del juego.


Características

🌠 Un universo que evoluciona con eventos y condiciones

El estado del universo cambia dinámicamente según las condiciones y eventos del juego. Dependiendo de cómo se desarrolle tu partida, encontrarás diferentes escenarios y situaciones cósmicas.

🏁 Un final real

Esto no es solo un juego de números. STELLAR EPOCH: APHELION tiene una conclusión apropiada esperándote. Cada mejora y recurso que acumulas te acerca a un objetivo significativo, dándote una satisfacción genuina cuando lo alcanzas.

📱 Funciona en móvil y PC

El juego está optimizado tanto para smartphones como para navegadores de escritorio. Juega donde te sea cómodo — tu progreso siempre está a una pestaña de distancia.

🌍 Soporte multilingüe

El juego soporta múltiples idiomas, para que jugadores de todo el mundo puedan disfrutarlo en su lengua materna. Es un juego construido para una audiencia global.

🪐 Espacio 3D renderizado con Three.js

El universo cobra vida usando Three.js, una biblioteca JavaScript 3D. El cosmos se renderiza en tiempo real directamente en tu navegador, sumergiéndote en un mundo profundamente inmersivo.


¿Qué es un juego incremental?

Los juegos incrementales (también llamados juegos idle o clicker) son un género donde acumulas recursos gradualmente, desbloqueas mejoras y expandes la escala de tu operación paso a paso. El atractivo reside en la sensación de logro que proviene de pequeños progresos constantes que se suman a algo enorme — y en poder jugar a tu propio ritmo.


¿Para quién es esto?

  • Personas que buscan un juego rápido al que puedan acceder sin instalaciones
  • Fans de los entornos espaciales y de ciencia ficción
  • Fans de los juegos incrementales / idle
  • Jugadores que disfrutan juegos con una historia y un final real
  • Cualquiera que quiera jugar casualmente en móvil o PC
  • Jugadores que prefieren jugar en un idioma distinto al japonés

Cómo jugar

¡Solo abre tu navegador y ve a https://stellar-epoch.sloth255.com/ — eso es todo!


Aspectos técnicos destacados

Arquitectura general

Tecnología Propósito
React + TypeScript Toda la UI
Zustand Gestión del estado del juego
Vite Herramienta de build
Firebase Analytics
AWS S3 + CloudFront Alojamiento

Bucle del juego: La función tick() en el store de Zustand se llama a intervalos regulares desde un hook useGameLoop, gestionando la producción de energía, instalaciones y aparición de encuentros en una sola pasada. El estado se persiste en localStorage.


Renderizado 3D con Three.js / React Three Fiber

Todo el renderizado 3D está centralizado en SpaceScene.tsx. Los puntos técnicos clave se describen a continuación.

1. Shaders GLSL personalizados (Sol, Atmósfera, Disco de acreción)

  • Shader del Sol: El fragment shader usa el producto punto de la normal de la superficie y la dirección de la cámara para generar un efecto de brillo de corona. El uniform time se actualiza en cada frame para crear una animación de pulso. Cuando se activa un destello, flareIntensity se transiciona suavemente usando lerp().
  • Shader de atmósfera: Usando la misma técnica de producto punto de normales, se renderiza una atmósfera planetaria que solo colorea el borde (efecto tipo Fresnel) mediante renderizado BackSide.
  • Disco de acreción de agujero negro: Un patrón de turbulencia construido a partir de múltiples ondas sinusoidales superpuestas crea un gradiente que brilla blanco intenso en el centro y se desvanece a rojo oscuro en los bordes. Los UVs de RingGeometry se corrigen manualmente para mapear radialmente según lo previsto.

2. Animación por frame con useFrame

  • Órbitas de planetas y lunas: angleRef se incrementa en cada frame, y position.x/z se calcula con funciones trigonométricas — un enfoque ligero que no requiere simulación física.
  • Las referencias a objetos se almacenan con useRef para que las posiciones, rotaciones y uniforms puedan escribirse directamente sin provocar re-renderizados de React, manteniendo el rendimiento alto.

3. Renderizado eficiente de grandes cantidades de objetos con InstancedMesh

Las matrices de un objeto dummy THREE.Object3D se copian en el InstancedMesh, reduciendo todas las instancias a una sola llamada de draw.

4. Sistemas de partículas (BufferGeometry)

  • Espiral galáctica: Un Float32Array de 5,000 puntos se pre-genera. Se colocan cuatro brazos espirales usando coordenadas polares uniformemente espaciadas con dispersión aleatoria, y la atenuación de brillo mediante exp(-dist/18) crea una galaxia de aspecto natural que es más brillante en el centro.
  • Efecto supernova: Los vectores de velocidad están embebidos en userData, y las posiciones se calculan como elapsed * velocity dentro de useFrame, haciendo que las partículas salgan volando hacia afuera en una esfera.
  • Red cósmica: Un grafo de proximidad de 200 nodos se renderiza como LineSegments, conectando dos nodos cualquiera dentro de la distancia 12.

5. Control de cámara consciente de la fase

A medida que el juego avanza por las fases 1–7, la distancia de retroceso de la cámara cambia, produciendo una expansión visual de escala desde un sistema solar → galaxia → estructura cósmica a gran escala. Se aplica una curva de easing personalizada (1 - (1-t)^3) mediante requestAnimationFrame para transiciones suaves.

6. Carga progresiva de texturas con Suspense

useTexture de @react-three/drei carga texturas de forma asíncrona y está envuelto en React Suspense. Mientras las texturas no se han cargado aún, se muestra un fallback solo con shader. Un uniform hasTexture se pasa a GLSL para cambiar dinámicamente entre renderizado texturizado y no texturizado.

7. Sacudida de cámara

Cuando se activa un encuentro Legendario, se implementa un simple efecto de sacudida añadiendo y restando un desplazamiento aleatorio a la posición de la cámara en cada frame mediante useThree() para manipulación directa de la cámara.