2010-04-26 23 views
21

Estoy trabajando en un programa Haskell para jugar juegos espaciales: tengo un gráfico de un grupo de "individuos" que juegan el dilema del prisionero, pero solo con sus vecinos inmediatos, y copiando las estrategias de las personas que mejor lo hacen.Imagen de la biblioteca de dibujo para Haskell?

He llegado al punto en el que necesito dibujar una imagen del mundo, y aquí es donde he tenido problemas. Dos de las posibles geometrías son fáciles: si las personas tienen cuatro u ocho vecinos cada una, entonces represento cada una como un cuadrado relleno (con el color correspondiente a la estrategia) y coloco el plano con estas. Sin embargo, también tengo una situación en la que las personas tienen seis vecinos (hexágonos) o tres vecinos (triángulos).

Mi pregunta, entonces, es: ¿Qué es una buena biblioteca de Haskell para crear imágenes y dibujar formas sobre ellas? Prefiero que cree PNG, pero no soy increíblemente quisquilloso. Originalmente estaba usando Graphics.GD, pero solo exporta enlaces a funciones para dibujar puntos, líneas, arcos, elipses y rectángulos no rotados, lo que no es suficiente para mis propósitos (a menos que quiera dibujar hexágonos píxel por píxel *). Estudié usando foreign import, pero está resultando un poco complicado (en parte porque la función de dibujo de polígonos requiere una matriz de estructuras gdPoint), y dado que mis requisitos pueden crecer, sería bueno usar una solución de Haskell y No tengo que ensuciarme con el FFI (aunque si se llega a un acuerdo, estoy dispuesto a hacerlo). ¿Alguna sugerencia?

* Que es también es una opción; cualquier consejo sobre cómo hacerlo también sería apreciado, aunque creo que una biblioteca sería más fácil.

EDIT: Muchas gracias a todos por sus sugerencias. Desafortunadamente, no pude obtener todas las bibliotecas necesarias de gtk2hs para construir, lo que descartó una gran cantidad de soluciones. Por diversas razones, después de probar todas sus respuestas, no pude instalar varias bibliotecas y descubrí que otras no podían hacer lo que quería, terminé decidiendo simplemente exportar más de una FFI para libgd y usarla en su lugar.

+0

posible duplicado de [biblioteca de Haskell para el dibujo 2D] (http://stackoverflow.com/questions/5612201/haskell-library-for-2d-drawing) –

Respuesta

2

¿Qué es una buena biblioteca Haskell para crear imágenes y dibujar formas sobre ellas?

Usted tiene bastantes opciones, a mi mente la siguiente han sido used for games:

Esos son los más comunes, y usted puede simplemente elegir basados ​​en características/familiaridad.

+0

He usado HOpenGL antes, pero el problema es que (por lo que yo sé) no se puede procesar en un archivo, sino solo en la pantalla; lo mismo (de nuevo, por lo que puedo decir) parece ser cierto para SDL y Wx. Aunque miraré hacia El Cairo. –

5

Cairo es una buena apuesta si desea generar PNG. Wumpus también parece prometedor, aunque nunca lo he usado. Si solo necesita verlo en la pantalla, graphics-drawingcombinators es una interfaz sencilla para OpenGL que hará lo que necesita en unas pocas líneas (consulte example.hs en la distribución).

+0

Definitivamente voy a mirar a El Cairo (e instalar gtk2hs ...) y Wumpus, ya que necesito guardar la imagen en un archivo. Sin embargo, 'graphics-drawingcombinators' se ve muy bien si alguna vez tengo que hacer cosas tipo HOpenGL en el futuro (aunque, para su información, el enlace que tiene apunta a' wumpus-core' nuevamente). –

+0

Se corrigió el destino del enlace. – luqui

6

He usado HOpenGL antes, pero el problema es que (por lo que puedo decir) no puede rendir a un archivo, pero sólo la pantalla; lo mismo (de nuevo, en cuanto a puedo decir) parece ser cierto para SDL y Wx. Voy a mirar en El Cairo, sin embargo.

Por alguna razón no puedo responder a esta publicación, así que tengo que citarla. Es incorrecto sobre GL y SDL, puede crear una superficie/búfer fuera de la pantalla o renderizar en texturas. Esas bibliotecas no necesitan esa función (y tampoco tiene mucho sentido) porque puede hacerlo fácilmente accediendo a los píxeles en el búfer y escribiéndolo usted mismo, incluso con los búferes de pantalla puede acceder a datos de píxeles.

El otro día me presenté a alguien cómo hacer esto con los enlaces Haskell SDL:

http://hpaste.org/fastcgi/hpaste.fcgi/view?id=25047

Usar una biblioteca que puede escribir en archivos PNG, lo más probable es que tome un puntero en bruto a un búfer de píxeles que puede obtener de SDL/GL o copiarlo a un formato que la biblioteca necesita.

Acabo de encontrar un Haskell binding for the library DevIL que puede generar archivos .PNG. Echa un vistazo a la función llamada writeImageFromPtr

+0

Oh, guau, ¡no había pensado en tratar de resolver el problema de esta manera! Esto parece realmente prometedor (especialmente porque gtk no se pudo instalar); Lo instalaré y veré si puedo hacerlo funcionar. –

+0

Olvidé mencionar una cosa más, si va a acceder a datos de píxeles que se muestran en los búferes de la pantalla, probablemente deba blit (copiar) todo el búfer en un búfer en la memoria del sistema, porque normalmente los búfers de la pantalla frontal/posterior están en VRAM y necesita bloquear el búfer/superficie que no desea bloquear la GPU con una operación de larga ejecución. También tenga en cuenta que SDL tiene una opción para crear una superficie de pantalla que se crea en la memoria del sistema. –

+1

Si va por este camino, debe usar * OpenGL's * acceso a la pantalla.SDL simplemente pensará que está vacío. Ver http://hackage.haskell.org/packages/archive/OpenGL/latest/doc/html/Graphics-Rendering-OpenGL-GL-ReadCopyPixels.html. – luqui

11

Los diagramas se ven muy bien, pero si quieres evitar cometer y mantenerte súper ligero, puedes generar svg directamente. El robo de Conrad Barski en http://www.lisperati.com/haskell/

type Point  = (Float,Float) 
type Color  = (Int,Int,Int) 
type Polygon = [Point] 

writePoint :: Point -> String 
writePoint (x,y) = (show x)++","++(show y)++" " 

writePolygon :: (Color,Polygon) -> String 
writePolygon ((r,g,b),p) = "<polygon points=\""++(concatMap writePoint p)++"\" style=\"fill:#cccccc;stroke:rgb("++(show r)++","++(show g)++","++(show b)++");stroke-width:2\"/>" 

writePolygons :: [(Color,Polygon)] -> String 
writePolygons p = "<svg xmlns=\"http://www.w3.org/2000/svg\">"++(concatMap writePolygon p)++"</svg>" 

colorize :: Color -> [Polygon] -> [(Color,Polygon)] 
colorize = zip.repeat 

[email protected][red,green,blue,yellow,purple,teal] = map colorize [(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255)] 

t0 = writeFile "tut0.svg" $ writePolygons (blue [[(100,100),(200,100),(200,200),(100,200)],[(200,200),(300,200),(300,300),(200,300)]]) 

hexagon c r = translateTo c basicHexagon where 
    basicHexagon = top ++ (negate r, 0):bottom 
    top   = [(r,0),(r * cos 1,(r * sin 1)),(negate (r * cos 1), r * (sin 1))] 
    bottom  = map (\(x,y)->(x,negate y)) (reverse top) 

translateTo (x,y) poly = map f poly where f (a,b)= ((a+x),(b+y)) 

t1 = writeFile "t1.svg" $ writePolygons (blue [hexagon (100,100) 50]) 

hexField r n m = let 
    mkHex n = hexagon (1.5*n*(r*2),(r*2)) r 
    row n = map mkHex [1..n] 
    aRow = row n 
    in concat [map (offset (r*x)) aRow |x<-[1..m]] 

offset r polys = map (oh r) polys where 
    oh r [email protected](x,y) = (x+(1.5*r),y+(r*sin 1)) 

t2 = writeFile "t2.svg" $ writePolygons (blue $ hexField 50 4 5) 

t2 carrera y cargar el archivo en Firefox o algún otro programa que soporta SVG.

t2.svg ,exported png http://img30.imageshack.us/img30/2245/93715707.png

Cuestiones relacionadas