Comunidad Game Maker

Ayuda => Desarrollo de Scripts => Mensaje iniciado por: Texic en Agosto 28, 2013, 04:20:33 PM

Título: Dibujar curvas bezier
Publicado por: Texic en Agosto 28, 2013, 04:20:33 PM
Creador: Texic

Version de GM utilizada:  :GM8:

Descripcion:
Se trata de dos scripts que pueden dibujar curvas bezier. Uno dibuja curvas cuadráticas (con sólo un punto de control entre el inicio y el fin) y otra cúbicas (con 2 puntos de control entre inicio y fin)

draw_bezier_quadratic
[gml]/*
argument0 = x del punto inicial
argument1 = y del punto inicial
argument2 = x del punto final
argument3 = y del punto final
argument4 = x del punto de anclaje
argument5 = y del punto de anclaje
*/
var p1x,p1y,p2x,p2y,p3x,p3y,pointsx,pointsy,c,t;
p1x=argument0
p1y=argument1
p2x=argument2
p2y=argument3
p3x=argument4
p3y=argument5
pointsx=ds_list_create()
pointsy=ds_list_create()
ds_list_add(pointsx,p1x)
ds_list_add(pointsy,p1y)
c=max(point_distance(p1x,p1y,p2x,p2y) div 20,4)
for (i=1;i<=c;i+=1)
{
t=i/c
ds_list_add(pointsx,(sqr((1-t)))*p1x+(2*(1-t)*t*p3x)+(sqr(t)*p2x))
ds_list_add(pointsy,(sqr((1-t)))*p1y+(2*(1-t)*t*p3y)+(sqr(t)*p2y))
}
for (i=0;i<=ds_list_size(pointsx)-2;i+=1)
{
draw_line(ds_list_find_value(pointsx,i),ds_list_find_value(pointsy,i),ds_list_find_value(pointsx,i+1),ds_list_find_value(pointsy,i+1))
}
ds_list_destroy(pointsx)
ds_list_destroy(pointsy)[/gml]

draw_bezier_cubic
[gml]/*
argument0 = x del punto inicial
argument1 = y del punto inicial
argument2 = x del punto final
argument3 = y del punto final
argument4 = x del punto de anclaje de inicio
argument5 = y del punto de anclaje de inicio
argument6 = x del punto de anclaje de fin
argument7 = y del punto de anclaje de fin
*/
var p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y,pointsx,pointsy,c,t;
p1x=argument0
p1y=argument1
p2x=argument2
p2y=argument3
p3x=argument4
p3y=argument5
p4x=argument6
p4y=argument7
pointsx=ds_list_create()
pointsy=ds_list_create()
ds_list_add(pointsx,p1x)
ds_list_add(pointsy,p1y)
c=max(point_distance(p1x,p1y,p2x,p2y) div 10,20)
for (i=1;i<=c;i+=1)
{
t=i/c
ds_list_add(pointsx,(power((1-t),3))*p1x+(3*sqr((1-t))*t*p3x)+(3*(1-t)*sqr(t)*p4x)+(power(t,3)*p2x))
ds_list_add(pointsy,(power((1-t),3))*p1y+(3*sqr((1-t))*t*p3y)+(3*(1-t)*sqr(t)*p4y)+(power(t,3)*p2y))
}
for (i=0;i<=ds_list_size(pointsx)-2;i+=1)
{
draw_line(ds_list_find_value(pointsx,i),ds_list_find_value(pointsy,i),ds_list_find_value(pointsx,i+1),ds_list_find_value(pointsy,i+1))
}
ds_list_destroy(pointsx)
ds_list_destroy(pointsy)[/gml]

Como siempre dejo un ejemplo adjunto. Aclaro que no hace falta recalcular siempre la curva, pueden hacerle las modificaciones pertinentes para quedarse con la lista de puntos y dibujarla sin recalcular
Espero que a alguno le sirva  :)
Saludos makeros!
Título: Re:Dibujar curvas bezier
Publicado por: Zela en Agosto 28, 2013, 05:37:43 PM
Woo!, No Los Conocía Con Este Nombre Curvas Bezier Sino Por Splines Cuadráticas ó Cubicas.

No Sabia Como Crear Splines De Manera Compacta, Con Esto Me Salvas Texic.

En Resumen Genial Aporte  ;D

PD: Aunque Son Conceptos Diferentes Pero Parecidos :)
Título: Re:Dibujar curvas bezier
Publicado por: Texic en Agosto 28, 2013, 09:39:32 PM
Cita de: Zela en Agosto 28, 2013, 05:37:43 PM
Woo!, No Los Conocía Con Este Nombre Curvas Bezier Sino Por Splines Cuadráticas ó Cubicas.

No Sabia Como Crear Splines De Manera Compacta, Con Esto Me Salvas Texic.

En Resumen Genial Aporte  ;D

PD: Aunque Son Conceptos Diferentes Pero Parecidos :)
Gracias, me llevo menos tiempo que el a* pathfinding en implementar. Tambien he escuchado el termino spline pero bezier fue el que mas a fuego quedo grabado en mi vocabulario jaja
Título: Re:Dibujar curvas bezier
Publicado por: brunoxzx en Agosto 29, 2013, 06:44:04 AM
Genial Texic. Es raro que en todos estos años nadie haya posteado un script para dibujar algún tipo curva.

El script se ve corto y eficiente. Normalmente yo uso los paths que creo dinamicamente para dibujar curvas en parte por flojo, pero también por que creo que pueden ser algo más eficientes, sin embargo no estoy seguro, lo que me gusta es que se puede definir un sin fin de puntos.

Sobre los nombres creo que spline es como el conjunto de tipos de curvas definidas en porciones, mientras que las belizer son solo un tipo de entre otros tipos splines.
Título: Re:Dibujar curvas bezier
Publicado por: Texic en Agosto 29, 2013, 07:12:29 AM
Mh con paths, si es buena idea, aunque creo que no se logra exactamente el mismo efecto, se ven un tanto diferentes colocando los mismos puntos de control, pero no deja de ser una excelente idea
Título: Re:Dibujar curvas bezier
Publicado por: brunoxzx en Agosto 29, 2013, 07:58:58 PM
Quieres probar?. así es como los dibujo:

draw_path.
[gml]
    //argument0 path
    /*argument1 presicion 1=perfecto valores, mayores lo hacen mas cuadrado
            (es cada cuantos pixeles se dibuja una linea, si vas a usar 1 puedes cambiar la función draw_line por draw point).*/
    if ( path_get_length(argument0)>0 ){
        var x1, y1, x2, y2, t;
        t=1/(path_get_length(argument0)/argument1);
   
        x1=path_get_x(argument0, 0);
        y1=path_get_y(argument0, 0);
   
        for(i=t; i<1; i+=t){
            x2=path_get_x(argument0, i);
            y2=path_get_y(argument0, i);
       
            draw_line(x1, y1, x2, y2);
       
            x1=x2;
            y1=y2;
        }
    }
[/gml]

Edit:Wow quien lo diría, ya existía una función para dibujar los paths. En fín, con está podrías dibujarlos en 3d, de cualquier ancho o diversos colores.
Título: Re:Dibujar curvas bezier
Publicado por: Texic en Agosto 29, 2013, 08:16:56 PM
Pero si está la función draw_path()
Título: Re:Dibujar curvas bezier
Publicado por: brunoxzx en Agosto 29, 2013, 08:27:47 PM
Cita de: brunoxzx en Agosto 29, 2013, 07:58:58 PM
Edit:Wow quien lo diría, ya existía una función para dibujar los paths. En fín, con está podrías dibujarlos en 3d, de cualquier ancho o diversos colores.

Sí increíblemente me acabo de dar cuenta, algo antes de ver tu post. Muy extraño por que ese script lo hice hace varios meses y creo haber buscado esa función. Bueno al menos es algo más personalizable, por ejemplo podrías usar los valores de velocidad del path, para definir distintos colores entre punto y punto.

Edit: Mira http://yal.cc/gamemaker-bezier-curve-path-simulation/ (http://yal.cc/gamemaker-bezier-curve-path-simulation/) alguien que quería exactamente lo mismo que hace mi script (y que aparentemente termino haciendo algo más complicado). Es prueba de que mi script no fue hecho inútilmente, xD.
Título: Re:Dibujar curvas bezier
Publicado por: Texic en Agosto 29, 2013, 09:54:46 PM
Cierto, pero el draw_path es bastante más eficiente y simple para el caso, cada uno tiene sus ventajas, depende del uso que le vayas a dar
Título: Re:Dibujar curvas bezier
Publicado por: ferhand en Septiembre 11, 2013, 11:41:55 PM
  Saludos Makero Texic:


   ¡Muy bueno!

  Ya hace tiempo, en un proyecto medio olvidado tuve que confeccionar unos "scripts" para crear y guardar la lista de puntos de una curva, pero yo utilicé como base un elemento "path" de GM.

  Si los encuentro te los enviaré a ver que crees.

  De todas formas tienes mis diez puntos. Muy útil.  ;D 
Título: Re:Dibujar curvas bezier
Publicado por: brunoxzx en Septiembre 12, 2013, 01:10:06 AM
Genial justo hoy voy a realizar los míos (en general me gusta entender estás cosas). Cuando los termine crees que debería postearlos por aquí?

Por cierto lo del A*, ¿que tal quedo? vamos queremos verlo ¿porqué no lo subes? Entiendo que gm ta tenga el A* implementado, pero seguro el tuyo es más versátil.
Título: Re:Dibujar curvas bezier
Publicado por: Texic en Septiembre 12, 2013, 01:16:33 AM
Jaja, lo tengo en el disco agonizante y me cuesta horrores conectarlo. Te recomiendo intentar hacerlo como experiencia, es muy interesante de realizar. Yo por mi parte empecé con un montón de objetos nodo que guardaban en un array conexión con sus consiguientes, luego estaba el generador de mapa que ponía los nodos donde no había obstáculos y el ir desde un nodo a otro usaba la idea de A* que es básicamente tener un peso para cada nodo conectado (que consiste en la suma de la distancia hasta el mismo, más la distancia desde él hasta la meta), hay que ir tachando los nodos usados para no volver a recorrerlos y seguir así hasta llegar a la meta. Obviamente necesita ajustes para funcionar a todo terreno, pero así funciona para los casos más simples