La misma nave en cada pantalla
Una tabla de clasificación diaria solo es justa si volar el mismo tramo de cueva es igual de difícil en un teléfono viejo y pequeño, una tablet a 144 Hz y un navegador de escritorio. Esto es lo que hizo falta, y lo que no pude igualar.
La entrada sobre la cueva diaria trata de hacer que el mundo sea idéntico para cada jugador. Esta trata de la otra mitad de la equidad: hacer que la nave se comporte de forma idéntica. Hay dos formas separadas en que un dispositivo puede cambiar cómo se juega, y necesitan dos correcciones separadas. Una es la frecuencia con la que se actualiza la pantalla. La otra es el tamaño de la pantalla.
Problema uno: la tasa de refresco
La nave tiene una posición y una velocidad. En cada fotograma, la gravedad o el empuje cambian la velocidad, y la velocidad cambia la posición. La forma obvia de escribir eso es:
vy += accel * dt; // update velocity
py += vy * dt; // then move by the NEW velocity
Parece inofensivo, pero es sutilmente incorrecto. La segunda línea finge que la nave ya pasó todo el fotograma viajando a su velocidad de fin de fotograma. Si la nave está acelerando, eso se pasa por la mitad de accel × dt² en cada fotograma. El problema es que dt, la duración del fotograma, es diferente en cada dispositivo, así que el exceso también es diferente, y una nave volaba una trayectoria ligeramente distinta en cada tasa de refresco.
Lo medí con un empuje mantenido durante medio segundo. La respuesta exacta es 225 píxeles. El integrador antiguo daba 228 a 144 Hz, 232 a 60 Hz y 240 a 30 Hz. Tres dispositivos, tres distancias distintas, con la misma entrada.
La solución es la regla del trapecio, que usa el promedio de la velocidad antes y después del fotograma:
const vyPrev = vy;
vy += accel * dt;
py += (vyPrev + vy) * 0.5 * dt; // average speed over the frame
Para una aceleración constante eso es exacto, sea cual sea la duración del fotograma. Reproducir un mismo esquema de entrada ahora da una dispersión de 0,000 píxeles entre 12 y 144 Hz. Antes era de 4,1 píxeles. Una prueba comprueba ambas mitades: que el nuevo integrador coincide en todas las tasas de refresco y que el antiguo realmente divergía, así que si alguien lo revierte, la prueba falla en lugar de que la tabla de clasificación se desvíe en silencio.
Dos advertencias honestas
No cerró la brecha de puntuación entre tasas de refresco. Lo esperaba. Un piloto simulado seguía marcando alrededor de un tercio más a 144 Hz que a 60 Hz después de todo. Esa brecha no es física. Es resolución de entrada: un pulgar solo puede pasar de mantener a no mantener en el límite de un fotograma, así que una pantalla más rápida da un control genuinamente más fino. Ningún integrador puede arreglar eso, y un bot que alterna su entrada en cada fotograma lo exagera respecto a un humano. La mitad física ahora es exacta, y el resto es una propiedad del hardware.
Es un nerfeo muy leve a 60 Hz. Una subida de medio segundo ahora cubre 225 píxeles en vez de 232. Dejé eso sin compensar. Si alguna vez una prueba en dispositivo real encontrara la nave lenta, la palanca es la constante de empuje, alrededor de un 3% más restauraría la vieja maniobra de medio segundo. Es un buen momento para decir que el empuje ya se ha cambiado dos veces por feedback de jugadores, y esa historia es la razón por la que soy cauteloso al tocarlo.
Problema dos: la altura de la pantalla
La gravedad en píxeles por segundo al cuadrado significa cosas muy distintas en un teléfono de 375 puntos de alto y una tablet de 520 puntos de alto. Si las constantes fueran las mismas, la misma subida cruzaría una fracción mucho menor de la pantalla en la tablet, y el juego se sentiría más pesado.
Así que las constantes se definen respecto a una altura de referencia de 440 puntos, la altura en horizontal del iPhone más grande, donde se ajustó y probó la sensación del juego. En cualquier otra pantalla, la gravedad, el empuje y la velocidad terminal se multiplican todas por H / 440. Como la mitad del hueco del corredor también se escala con la altura, cada trayectoria es geométricamente similar a la de referencia: la misma fracción del corredor cruzada por segundo, el mismo tiempo para ir de una pared a otra, la misma respuesta percibida. Una pantalla más grande obtiene una aceleración más pronunciada en píxeles, y una más pequeña una más suave, por diseño.
Eso viene con una regla para todo el código futuro: cualquier cosa que razone sobre el movimiento vertical debe basarse en proporciones. Una fracción de la velocidad terminal, una fracción de la altura. Nunca una constante bruta en píxeles por segundo comparada con la velocidad de la nave, porque ese número solo es correcto en un dispositivo. Si un literal es inevitable, se multiplica por la misma escala.
La versión web sigue la misma regla. La compilación de navegador limita su lienzo a 956 por 440, la misma huella que ese teléfono de referencia, así que el juego en un navegador es una copia en píxeles y física exacta de él. Una compilación web anterior tenía su propio multiplicador de sensación, que existía solo para combatir la blandura causada por un límite distinto, y se eliminó una vez que el límite coincidió.
Problema tres: la anchura de la pantalla
La altura es el eje vertical. La anchura es el horizontal, y es más sutil. Los obstáculos se colocan a distancias fijas en el mundo. La cueva se desplaza a una velocidad que incluye un factor para la anchura de la pantalla. Así que en una pantalla más ancha los mismos obstáculos pasan más rápido en términos de pantalla, y el tiempo que tienes para reaccionar a cada uno baja en proporción a la anchura.
Esto era una fuga real. Una tablet Android grande de unos 1280 puntos de ancho se enfrentaba a la cueva compartida aproximadamente 1,75 veces más rápido que un teléfono pequeño. Así que la anchura está limitada a 956 puntos en cada plataforma, la anchura del iPhone más ancho en horizontal. Un dispositivo más ancho que eso obtiene barras negras a izquierda y derecha. Es un no-op en los iPhone y solo limita las tablets Android grandes y los navegadores de escritorio.
El límite tiene un residuo que no he corregido. El radio de colisión del jugador se escala con la anchura mientras que el corredor se escala con la altura, así que en una tablet más cuadrada la nave es un poco más pequeña en relación con el hueco que en un teléfono, alrededor de un 20% más indulgente. Corregirlo significa cambiar la caja de colisión, lo cual es un cambio de sensación que necesita su propia prueba de juego, y se equivoca en la dirección indulgente, así que puede esperar.
Probar la equidad en vez de afirmarla
Nada de esto es visible al jugar. No puedes sentir unos pocos píxeles de desviación, y nadie juega la misma cueva en seis dispositivos a la vez. Así que cada afirmación tiene una prueba que la reproduce: la prueba de física integra una entrada fija a tasas de refresco de 12 a 144 Hz, y una prueba de cueva reproduce los generadores reales en seis tamaños de dispositivo y compara el resultado byte por byte. Una propiedad de equidad que no pruebas ya se ha roto silenciosamente, en mi experiencia.
En resumen, TUNL es justo entre pantallas de tres formas distintas (tasa de refresco, altura y anchura), cada una con una causa diferente, una solución diferente y un residuo diferente. Puedes ver el resultado tú mismo, en cualquier dispositivo que tengas, en la cueva de hoy.