< Volver 

Sword Masters: Dash

2024-09-15

Dash, la habilidad gratis con la que empieza todo jugador, te lanza hasta 50 studs hacia adelante. Por debajo hay un AlignPosition que tira de la raíz hacia un punto delante, un AlignOrientation que fija hacia dónde miras, y dos formas de parar: tocar un marcador invisible en el destino o que pasen 0.4 segundos.

LuauRobloxGameplayPhysics
Ir a vista rápida

Un dash son dos constraints y un temporizador.

Advertencia

Sword Masters quedó abandonado en octubre de 2024, y la mayoría de sus animaciones, sonidos e imágenes son del grupo dueño del juego, así que no se puede correr como antes y este sistema no se puede mostrar en video.

Resumen. Dash es la habilidad con la que empieza todo jugador de Sword Masters: aprietas la E y el personaje sale disparado hasta 50 studs en la dirección en que mira, con una animación, un sonido y una ráfaga de partículas. Es una habilidad instantánea en el sentido del sistema de habilidades, así que todo su trabajo pasa en el Use del servidor. El movimiento sale de dos constraints de física en la raíz del personaje: un AlignPosition que tira de ella hacia un punto 50 studs adelante y un AlignOrientation que la mantiene mirando hacia el mismo lado durante el dash. El dash termina con lo que llegue primero, que la raíz toque un marcador invisible puesto en el destino o que pasen 0.4 segundos. Este artículo recorre cada pieza, un detalle de ángulos de Euler que solo funciona porque los personajes están parados derechos, y God’s Dash, la variante para admins que reutiliza el mismo código.

1. El problema

Un dash tiene que sentirse instantáneo, tiene que ir hacia donde mirabas al apretar y no hacia donde giras a la mitad, y tiene que detenerse solo. También tenía que correr en el servidor, como todas las habilidades del juego, pero la física del personaje la simula el cliente del jugador, que tiene su propiedad de red. Escribir la posición frame a frame desde el servidor pelearía contra esa propiedad y se vería a tirones para quien hace el dash.

Los constraints evitan ese problema. Si el servidor pone un AlignPosition dentro del personaje, el constraint se replica y lo simula el dueño del ensamblaje, que es el propio cliente del jugador, así que quien hace el dash ve un movimiento suave, y los demás ven el resultado por la replicación normal.

2. El destino

Cuando corre Use, el servidor calcula el destino una sola vez:

pfin=p0+Dfˆ

donde p0 es la posición de la raíz, fˆ el vector hacia donde mira y D el MoveStuds de la habilidad, 50 en el Dash. El vector se toma en el instante en que aprietas, así que girar la cámara a mitad del dash no cambia el destino.

3. Tirar

DashTo es un AlignPosition guardado como plantilla dentro del módulo. El servidor lo clona, le pone el destino como posición objetivo y lo engancha al RootAttachment de la raíz. Su Responsiveness sale del MoveSpeed de la habilidad, 30. El archivo de datos lo llama “studs per second”, pero no es una velocidad: es qué tan rígido intenta cerrar la distancia el constraint, y la velocidad real sale de eso combinado con los límites de fuerza y velocidad de la plantilla.

El corte a los 0.4 s le pone un techo a lo que puede recorrer el dash. Llegar a los 50 studs completos en ese tiempo exige un promedio de

v‾=500.4=125 studs/s

unas ocho veces la velocidad de caminar por defecto, que es 16. Si el constraint no llega a tiempo, el dash simplemente se detiene donde esté a los 0.4 s. Un dash contra una pared empuja contra la pared hasta que se acaba el tiempo, porque las colisiones del personaje siguen funcionando mientras el constraint tira.

4. Mantener hacia dónde miras

El personaje ya trae un AlignOrientation en la raíz. Dash le pone como objetivo la orientación actual de la raíz y lo activa mientras dura el dash, así que el personaje no puede girar en el aire aunque el jugador mueva la cámara o el stick:

local ao:AlignOrientation = hrp.AlignOrientation
ao.CFrame = CFrame.Angles(hrp.CFrame:ToOrientation());

Esa línea funciona por una razón que no es obvia. ToOrientation devuelve ángulos (α,β,γ) pensados para CFrame.fromOrientation, que aplica las rotaciones en orden Y, X, Z, mientras que CFrame.Angles las aplica en orden X, Y, Z:

RYXZ=Ry(β)Rx(α)Rz(γ),RXYZ=Rx(α)Ry(β)Rz(γ)

En general son rotaciones distintas. Pero la raíz de un personaje parado solo tiene giro horizontal: α=γ=0, y con esos dos en cero los dos productos dan Ry(β). Si el personaje estuviera inclinado al hacer el dash, la orientación objetivo saldría un poco mal. La inversa correcta es CFrame.fromOrientation(hrp.CFrame:ToOrientation()), o directamente la rotación de la propia raíz.

5. Parar

Hay dos salidas. Al empezar, el dash pone en el destino una parte anclada, invisible y sin colisión de 0.1 studs y escucha su Touched. Si una parte del propio personaje del jugador la toca, el dash termina ahí. Y un task.delay(0.4, ...) lo termina en cualquier caso. Las dos llaman a la misma función, que destruye el AlignPosition, desconecta el marcador, lo destruye y desactiva el AlignOrientation. Corre dos veces cuando el marcador salta primero, y destruir o desconectar lo que ya no existe no hace nada, así que no necesita guarda.

El marcador solo escucha al jugador que hizo el dash. Otro jugador que pase por encima no termina el dash ajeno.

6. Animación y efectos

Dash tiene dos animaciones que se alternan. El servidor guarda un contador AnimationState en los datos del jugador para esta habilidad, reproduce la pista en esa posición y lo avanza, volviendo a la primera al final de la lista. Dos dashes seguidos reproducen animaciones distintas, que se lee mucho menos mecánico que repetir la misma.

El sonido empieza 0.4 s dentro del clip, saltándose el ataque, y cada emisor de partículas bajo DashFX en la raíz emite dos partículas que después se desvanecen, subiendo su transparencia de 0.8 a 1.0 en 21 frames, más o menos un tercio de segundo a 60 fps. Cuando el dash termina, la transparencia vuelve a su valor inicial para el siguiente.

7. God’s Dash

God’s Dash es la versión para admins y reutiliza el código con cuatro cambios. Recorre 65 studs en vez de 50, su destino está un stud más arriba, no tiene cooldown y cura 10 puntos de vida mientras emite las partículas de curación además de las suyas. Que quepa en cuatro diferencias es el argumento a favor de haber escrito el Dash con sus números en datos y no en el código.

8. Limitaciones

Hay una pieza muerta. Dash también clona DashDirection, un LinearVelocity, y le pone como LineDirection el vector (fz,0,−fx), la perpendicular horizontal al vector hacia donde mira, pero nunca lo emparenta, así que no hace nada antes de destruirse.

La firma compartida del sistema de habilidades también se nota aquí. El Use del Dash declara un tercer parámetro, vfxName, para elegir el efecto, pero el manager llama a todos los Use con los mismos argumentos, y el tercero es el remote Loaded. La revisión type(vfxName) == "string" es lo que salva la llamada y cae en "DashFX".

Y, como en todas las habilidades del juego, el cooldown de 5 segundos solo se revisa en el cliente.

9. Lo que me dejó

Mover personajes con constraints en vez de escribir posiciones desde el servidor fue la decisión más importante, y el argumento de la propiedad de red de la sección 1 es lo que me convenció. La doble salida, marcador o temporizador, también es un patrón que volví a usar: un evento termina la acción cuando todo sale bien y un temporizador garantiza que termine cuando no. Lo que cambiaría son los nombres. MoveSpeed no es una velocidad y MoveStuds es una distancia que el dash no siempre recorre. Con nombres como Responsiveness y MaxDistance, la sección 3 no habría hecho falta.

Este texto de Mastedore. Todos los derechos reservados.