Cómo crear una pista a lo largo de una curva en GameMaker / Sudo Null IT News

¿Cómo crear una curva en GameMaker? ¿Cómo puedo utilizar esta curva y textura de carretera para crear una ruta? ¿Necesitas saber trigonometría para esto? ¿Cómo utilizar el conocimiento sobre vectores para esto?

¡Hola a todos! El programador Alexander Kondyrev está con usted. En este artículo responderé las preguntas anteriores.

Cuando YoYo Games adquirió GameMaker, recibió un nuevo IDE y se convirtió en GameMaker Studio. El otro día, un colega me dijo que GameMaker Studio 2 ahora vuelve a llamarse simplemente GameMaker. Ya estoy acostumbrado a llamarlo GMS2, ​​así que no noté este cambio. Me estoy corrigiendo y ahora lo llamo GameMaker o GM nuevamente.

Cuando comencé a programar juegos, no entendía cómo usar las curvas.

Los objetos construidos a lo largo de curvas parecían mágicos. En ese momento no me di cuenta de un concepto importante: una persona no puede distinguir entre una línea curva y una línea dividida en muchos pequeños segmentos rectos. Este es el concepto que usaré en este tutorial. Construiremos una línea curva y la dividiremos en segmentos rectos para crear una ruta a partir de ellos.

Para empezar, dibujé en papel una curva por la que quiero construir una carretera.

En la plaza se destaca un fragmento de la carretera, que examinaré con más detalle en la figura siguiente.

-3

Este es un fragmento ampliado de una curva de un cuadrado. La imagen muestra que dividí este fragmento en diez piezas del mismo largo. Se dibujan cuadrados encima y debajo de cada pieza. Cada cuadrado está separado por una línea de puntos, lo que muestra que están formados por triángulos. Aunque estas figuras se parecen mucho a cuadrados, en realidad son trapecios.

Se estrechan donde la curva es cóncava y se ensanchan donde es convexa.

En el siguiente diagrama veremos un fragmento con más detalle.

-4

AB y BC son dos partes de la curva. Tenga en cuenta que en este diagrama he reducido el número de triángulos por fragmento de curva de cuatro a dos. Mi fragmento de carretera, construido a lo largo de una curva, constará de los triángulos A2A1B1 y B1B2A2. Para construirlos necesito encontrar las coordenadas de los puntos A1, A2, B1, B2.

Ahora iré a GM para construir una curva de prueba allí.

-5

Para hacer esto, agrego una curva Path1 en un nuevo proyecto; en GameMaker se llaman camino o caminos.

-6

Abro Habitación1 y creo una capa Ruta_1 en esta habitación.

-7

En esta capa activo la curva creada Path1.

-8

Una curva puede tener un principio y un final abiertos, o puede estar cerrada, con el punto final conectado al punto inicial. Para una pista circular necesito una curva cerrada, así que en la casilla Cerrado Puse una marca. Los caminos pueden consistir en líneas rectas o curvas tangentes a estas líneas. Para giros suaves en la autopista, selecciono la segunda opción y presiono el botón Curva suave. A continuación, coloco los puntos y los muevo por la habitación para crear la curva deseada. En la captura de pantalla muestro la curva resultante.

-9

Agrego Objeto1 al proyecto y creo una instancia del mismo en la sala. Además escribiré el código en este objeto.

Para renderizar la carretera usaré un buffer de vértices. Para hacer esto en el caso Crear Creo un formato de vértice para este búfer y el búfer en sí.

-10

De la tercera a la séptima línea creo el formato de vértice. Contendrá coordenadas de vértice, coordenadas de textura y color. Para este ejemplo, no necesito un color y solo necesito dos coordenadas en el vértice: X e Y. Sin embargo, en este tutorial usaré el sombreador estándar de GameMaker, así que dejaré el formato de vértice de esta manera. .

De las líneas nueve a trece, creo un búfer de vértices y lo transfiero a la memoria de video usando la función vértice_congelado. Todas estas líneas ya han sido descritas en el artículo Sobre gráficos 3D. Agregaré los vértices calculados al búfer entre las líneas diez y doce.

Ahora necesitas calcular las coordenadas de los puntos A1, A2, B1, B2. Para ello, introduciré varias variables.

-11

En la segunda línea creo una matriz líneas_array para almacenar las coordenadas de los vértices calculados. Lo llamo líneas porque los vértices se almacenarán en pares y, por lo tanto, formarán líneas. En la tercera línea guardo el valor 64 en la variable ancho, que denota el ancho de la ruta. Y en la cuarta línea encuentro la mitad de esta longitud y la guardo en la variable width_half. En la quinta línea, creo una variable pth y le asigno el valor de la ruta creada Path1. En la sexta línea asigno el valor 8 a la variable part_size. Quiero que haya aproximadamente esta cantidad de píxeles en cada fragmento de ruta. Cuantos más píxeles haya en cada fragmento, más angular será el camino. Cuantos menos píxeles haya en cada fragmento, más suave será el camino, pero se necesitarán más triángulos para dibujarlo. Digo “aproximadamente” la longitud del fragmento porque no conozco la longitud de toda la curva, y esta longitud no será necesariamente un múltiplo de ocho.

En la séptima línea, usando la función path_get_length, obtengo y almaceno la longitud de la curva en la variable path_length. En la octava línea, divido enteramente la longitud de la curva por la longitud del fragmento para obtener el número de fragmentos en la curva. En la novena línea, divido la longitud de la curva por el número de fragmentos para ajustar la longitud de cada fragmento. En la décima línea, divido el tamaño del fragmento por el ancho del trazo para encontrar este tamaño en coordenadas de textura y lo almaceno en la variable tex_frac.

A continuación, usaré un bucle para recorrer todos los segmentos de la curva, calcularé las coordenadas A1, A2, B1, B2 y las almacenaré en una matriz.

Aquí nuevamente daré un diagrama de un trapezoide con los vértices requeridos.

-12

En el siguiente código estoy calculando el vector AB. Con su ayuda, encuentro el vector ubicado a la izquierda de AA1 y el vector ubicado a la derecha de AA2. Usando estos vectores, calculo las coordenadas de los puntos deseados A1 y A2 y luego las guardo en una matriz. En los pasos siguientes del ciclo, repito este procedimiento para todas las demás partes de la curva.

-13

Veamos el código proporcionado con más detalle. Desde la línea decimocuarta a la decimonovena, calculo las coordenadas de los puntos A y B. Esto se hace usando las funciones path_get_x y path_get_y. A estas funciones se les debe pasar una curva y un valor de cero a uno. Cero indica el comienzo de la curva, uno indica su final. Para encontrar el valor deseado, debe dividir el índice por el número de partes. En el bucle, itero sobre todos los puntos calculados, por lo que el índice de cada punto corresponde al iterador i. Dentro de cada paso del ciclo, para calcular el vector, es necesario encontrar las coordenadas de dos puntos, respectivamente, el índice del segundo punto será i+1.

De las líneas veinte a veinticuatro, calculo el vector, encuentro su longitud y lo normalizo. La longitud de un vector normalizado siempre es igual a uno. Para encontrar un vector, debes restar las coordenadas del punto A de las coordenadas del punto B. Usando la función point_distance, se calcula la longitud del vector. Luego, las coordenadas del vector se dividen por su

longitud para encontrar el vector unitario.

Desde la línea vigésimo quinta a la trigésima segunda, se calculan los vectores izquierdo y derecho. El ángulo entre el vector unitario y los vectores deseados es siempre de 90 grados, por lo que no es necesario utilizar fórmulas trigonométricas aquí. Intercambio las coordenadas del vector unitario y agrego un signo menos a una de las coordenadas. De esta forma se encuentran los vectores unitarios izquierdo y derecho. Los multiplico por la mitad del ancho de la ruta para obtener la longitud requerida.

Desde la línea trigésimo tercera a la trigésima séptima, sumo los vectores encontrados a las coordenadas del punto A para obtener las coordenadas de los puntos deseados A1 y A2. Guardo los valores resultantes en la matriz lines_array.

Para mostrar la ruta, dibujé una textura de 16×16 píxeles. En la configuración debes marcar la casilla Página de textura separada; de lo contrario, GameMaker agregará esta textura a la página de textura general en el momento de la compilación. Si esto sucede, entonces los cálculos proporcionados en este manual no se podrán utilizar y tendrá que utilizar un método diferente.

-14

A continuación, debe agregar los vértices al búfer. Además de las coordenadas espaciales, necesitaré coordenadas de textura. Dibujaré otro diagrama:

-15

Este diagrama muestra un cuadrado que representa la textura. El cuadrado está dividido por líneas de puntos en 8 segmentos idénticos. La esquina superior izquierda de la textura tiene coordenadas (0,0), la esquina inferior derecha tiene coordenadas (1,1). En el centro de la textura están las coordenadas (x=0,5, y=0,5). Anteriormente calculé la variable tex_frac. Este valor representa la distancia horizontal entre dos líneas de puntos.

En el siguiente fragmento termino de construir el búfer de vértices.

-16

Aquí vuelvo a recorrer todos los puntos y formo a partir de ellos en cada paso dos triángulos que forman un trapezoide. Desde la línea quincuagésima primera hasta la sexagésima primera, extraigo dos líneas adyacentes de la matriz. Por conveniencia, guardo las coordenadas de las líneas en variables separadas ax1, ay1, ax2, ay2, bx1, by1, bx2, by2. Por el índice actual i obtengo la primera línea, y por el índice i+1 obtengo la siguiente. Observe la construcción en la línea cincuenta y dos: % es un operador “módulo” o “mod” que devuelve el resto de la división. ¿Por qué se utiliza este diseño? En la última iteración del ciclo, i+1 irá más allá de la longitud de la matriz, lo que provocaría un error. Pero el operador de módulo devuelve 0 en este caso y no se produce ningún error. Esto proporciona la primera línea de la matriz, que es exactamente lo que se necesita para el último valor. No había usado esta construcción antes y recurrí a condiciones adicionales u otras soluciones, lo que hizo que el código fuera más difícil de leer.

Desde la línea sesenta segunda a la setenta, agrego el primer triángulo al búfer

A1B1A2. Desde la línea setenta y dos a la octogésima del buffer, se agrega el segundo triángulo B1B2A2.

La adición de vértices al búfer se describió en detalle en el artículo “Acerca de los gráficos 3D”.

Normalmente, para las coordenadas de textura, se acostumbra utilizar U y V en lugar de X e Y, respectivamente. La coordenada V para los puntos A1 y B1 siempre será igual a cero, y para los puntos

A2 y B2: uno. Esto se puede ver en el diagrama de arriba. La coordenada U se calcula multiplicando el índice actual i o j por la longitud del fragmento de textura tex_frac. Notarás que los valores U excederán uno en algún momento, pero al habilitar gpu_set_texrepeat(true) dichos valores son aceptables porque la textura se repetirá en todas las direcciones. En la captura de pantalla, el búfer road_buff está resaltado en azul. Esto significa que eliminé la palabra var al declarar esta variable para que esté disponible no solo en el evento Crear, sino también en el evento Dibujar.

Todo lo que queda es dibujar el búfer creado en la pantalla. A continuación se muestra el código del evento Draw.

-17

En la segunda línea almaceno el puntero de textura en una variable tex. Lo devuelve la función sprite_get_texture, a la que se le pasa el nombre del sprite y el fotograma para el que desea obtener un puntero de textura. Tengo un cuadro, por lo que el valor del cuadro es cero.

En la tercera línea activo la repetición de textura como se mencionó anteriormente. En la cuarta línea desactivo el filtrado. Esto no es necesario, pero estoy usando una textura de píxeles y no quiero que se interpolan sus colores. En la sexta línea usando la función.

vertex_submit Dibujo un búfer de vértices en la pantalla. A esta función se le pasa un búfer de vértices road_buff , pr_trianglelist significa que los vértices en el búfer pasado describen triángulos y tex es un puntero a una textura.

Comenzamos la recopilación y vemos en pantalla la ruta dibujada.

-18

En este artículo, construí una pista curva en GameMaker y la mostré en la pantalla. En el proceso, descubrí que la construcción requiere conocimientos básicos de vectores y no requiere ningún conocimiento de trigonometría. El artículo resultó mucho más largo que los anteriores. Escribe en los comentarios si te pareció demasiado largo o, por el contrario, perfecto.

Gracias por leer el artículo hasta el final. Espero que lo hayas disfrutado y hayas aprendido algo nuevo. Si es así, vote sí; tal vez así más gente se entere.

Ahora intento publicar un artículo por semana. Suscríbete para no perderte nuevas publicaciones.

Si te gustó este artículo, también te recomiendo consultar otros recursos sobre programación en GameMaker:

  1. Artículo sobre sombreadores

  2. Sobre gráficos tridimensionales. Parte 1 de 2

  3. Sobre gráficos tridimensionales. Parte 2 de 2

¡Gracias por su atención!

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *