2010-04-26 6 views
21

Ich arbeite an einem Haskell-Programm zum Spielen von räumlichen Spielen: Ich habe eine Grafik von einer Reihe von "Individuen", die das Gefangenendilemma spielen, aber nur mit ihren unmittelbaren Nachbarn und kopieren die Strategien der Leute, die es am besten können.Bildzeichnungsbibliothek für Haskell?

Ich habe einen Punkt erreicht, wo ich ein Bild von der Welt zeichnen muss, und hier habe ich Probleme bekommen. Zwei der möglichen Geometrien sind einfach: Wenn Menschen jeweils vier oder acht Nachbarn haben, dann repräsentiere ich jede als gefülltes Quadrat (mit der Strategie entsprechenden Farbe) und kachle die Ebene mit diesen. Ich habe jedoch auch eine Situation, in der Menschen sechs Nachbarn (Sechsecke) oder drei Nachbarn (Dreiecke) haben.

Meine Frage ist dann: Was ist eine gute Haskell-Bibliothek zum Erstellen von Bildern und Zeichnen von Formen auf ihnen? Ich würde es vorziehen, dass es PNGs erstellen, aber ich bin nicht unglaublich wählerisch. Ursprünglich verwendete ich Graphics.GD, aber es exportiert nur Bindungen an Funktionen zum Zeichnen von Punkten, Linien, Bögen, Ellipsen und nicht gedrehten Rechtecken, was für meine Zwecke nicht ausreicht (es sei denn, ich möchte Hexagone Pixel für Pixel * zeichnen). Ich habe mich mit foreign import beschäftigt, aber es erweist sich als etwas mühsam (teilweise, weil die Polygon-Zeichnung-Funktion ein Array von gdPoint Strukturen erfordert), und da meine Anforderungen wachsen können, wäre es nett, eine In-Haskell-Lösung zu verwenden Ich muss nicht mit dem FFI herumalbern (wenn es aber hart auf hart kommt, bin ich dazu bereit). Irgendwelche Vorschläge?

* Das ist auch eine Option, eigentlich; Irgendwelche Tipps, wie man das macht, würden auch geschätzt werden, obwohl ich denke, dass eine Bibliothek einfacher wäre.

EDIT: Vielen Dank für Ihre Anregungen. Leider konnte ich nicht alle benötigten Bibliotheken von gtk2hs erstellen, was viele Lösungen ausschloss. Aus verschiedenen Gründen, nachdem ich alle deine Antworten ausprobiert habe, eine Reihe von Bibliotheken nicht installiert habe und festgestellt habe, dass andere nicht tun können, was ich wollte, entschied ich mich, einfach mehr von einem FFI für libgd zu exportieren und stattdessen zu verwenden.

+0

möglich Duplikat [Haskell-Bibliothek für 2D-Zeichnung] (http://stackoverflow.com/questions/5612201/haskell-library-for-2d-drawing) –

Antwort

2

Was ist eine gute Haskell-Bibliothek zum Erstellen von Bildern und Zeichnen von Formen auf ihnen?

Sie haben durchaus ein paar Optionen, meiner Meinung nach haben die folgende all used for games gewesen:

Dies sind die häufigsten, und Sie können nur basierend auf Funktionen/Vertrautheit wählen.

+0

Ich habe HOpenGL verwendet zuvor, aber das Problem ist, dass (soweit ich das beurteilen kann) es nicht zu einer Datei rendern kann, sondern nur auf dem Bildschirm; das gleiche (soweit ich das beurteilen kann) scheint für SDL und Wx wahr zu sein. Ich werde jedoch nach Kairo schauen. –

5

Cairo ist eine gute Wette, wenn Sie PNGs generieren möchten. Wumpus sieht auch vielversprechend aus, obwohl ich es nie benutzt habe. Wenn Sie es nur auf dem Bildschirm sehen müssen, ist graphics-drawingcombinators eine einfache Schnittstelle zu OpenGL, die in wenigen Zeilen das tut, was Sie brauchen (siehe example.hs in der Distribution).

+0

Ich werde auf jeden Fall nach Kairo schauen (und gtk2hs installieren ...) und Wumpus, da ich das Bild in einer Datei speichern muss. Allerdings 'Grafik-drawingcombinators' sieht wirklich cool, wenn ich jemals HOpenGL-Typ Sachen in der Zukunft (obwohl, nur FYI, der Link Punkte müssen auf' wumpus-core' wieder) müssen tun. –

+0

Das Verknüpfungsziel wurde korrigiert. – luqui

6

Ich habe HOpenGL vor verwendet, aber das Problem ist, dass (soweit ich das beurteilen kann) in eine Datei nicht wiedergeben kann, sondern nur der Bildschirm; die gleiche (wieder soweit ich sagen kann) scheint wahr von SDL und Wx zu sein. Ich werde jedoch nach Kairo schauen, .

Aus irgendeinem Grund kann ich nicht auf diesen Beitrag antworten, also muss ich es zitieren. Sie sind in Bezug auf GL und SDL nicht korrekt, Sie können eine Offscreen-Oberfläche/einen Puffer erstellen oder eine Textur rendern. Diese Bibliotheken benötigen keine solche Funktion (und machen auch keinen Sinn), weil Sie es ganz einfach selbst machen können, indem Sie auf Pixel im Puffer zugreifen und sie selbst ausschreiben, selbst mit den Bildschirmpuffern können Sie auf Pixeldaten zugreifen.

Erst neulich ich jemand zeigte, wie dies mit den Haskell SDL Bindungen zu tun:

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

Verwenden Sie eine Bibliothek, die PNG-Dateien schreiben können, werden sie am meisten nehmen wahrscheinlich einen Rohzeiger zu Pixel-Puffer, den Sie von SDL/GL erhalten oder in ein Format kopieren können, das die Bibliothek benötigt.

Ich habe gerade eine Haskell binding for the library DevIL ausgeben kann PNG-Dateien. Überprüfen Sie die Funktion aus aufgerufen writeImageFromPtr

+0

Oh, wow - ich hatte nicht darüber nachgedacht, das Problem auf diese Weise zu lösen! Das sieht sehr vielversprechend aus (vor allem, da gtk nicht installiert werden konnte); Ich werde das installieren und sehen, ob ich es zum Laufen bringen kann. –

+0

Ich habe vergessen, eine Sache zu nennen, wenn du gehst, Pixeldaten zuzugreifen, die in den Bildschirmpuffer gerendert wird wahrscheinlich sollten Sie den gesamten Puffer in einen Puffer im Systemspeicher, weil in der Regel des Vorder-/Rückseite Bildschirmpuffer blitten (Kopie) sind in VRAM und Sie müssen den Puffer/die Oberfläche sperren, die Sie die GPU mit einer lang laufenden Operation nicht blockieren möchten. Beachten Sie auch, dass SDL eine Option verfügt über eine Bildschirmoberfläche zu schaffen, die im Systemspeicher erstellt wird. –

+1

Wenn Sie diesen Weg gehen, sollten Sie * OpenGL * Zugriff auf den Bildschirm verwenden.SDL wird einfach denken, es ist leer. Siehe http://hackage.haskell.org/packages/archive/OpenGL/latest/doc/html/Graphics-Rendering-OpenGL-GL-ReadCopyPixels.html. – luqui

11

Diagramme sieht so cool, aber wenn Sie zu begehen vermeiden wollen und superleichten bleiben, könnten Sie svg direkt generieren. Stehlen von Conrad Barski bei 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) 

Lauf t2 und laden Sie die Datei in Firefox oder einem anderen Programm, das svg unterstützt.

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