2017-10-28 3 views
1

Ich bin verpflichtet, eine einfache Animation mit haskell Glanz zu erstellen. Ich möchte, dass in den ersten 4 Sekunden jedes Rechteck seine Farbe in eine dunklere ändert. Das Problem ist, dass nach einer relativ langen Zeit der Verlinkung, passiert nichts wirklich -Gloss Funktion `animiert` scheint nichts zu tun

enter image description here

Alle Rechtecke erscheinen und sie ändern sich nicht Farbe

Dies ist der folgende Code i verwendet -

window :: Display 
window = InWindow "Simon" (width, height) (offset, offset) 

background :: Color 
background = black 

data SimonGame = Game { 
    rectangleGreen::Picture, 
    rectangleRed::Picture, 
    rectangleBlue::Picture, 
    rectanglYellow::Picture 
} deriving Show 

initialState :: SimonGame 
initialState = Game 
    { rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60, 
    rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60, 
    rectangleBlue = translate (0) (100) $ color blue $ rectangleSolid 60 60, 
    rectanglYellow = translate (0) (-100) $ color yellow $ rectangleSolid 60 60 
    } 

render :: SimonGame -> Picture 
render game = pictures 
       [ rectangleGreen game, 
       rectangleRed game, 
       rectangleBlue game, 
       rectanglYellow game 
       ] 

updateBoard :: Float-> SimonGame -> SimonGame 
updateBoard 1.0 game = game { 
           rectangleGreen = translate (-100) (0) $ color (dark green) $ rectangleSolid 60 60, 
           rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60, 
           rectangleBlue = translate (0) (100) $ color blue $ rectangleSolid 60 60, 
           rectanglYellow = translate (0) (-100) $ color yellow $ rectangleSolid 60 60 
          } 
updateBoard 2.0 game = game { 
           rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60, 
           rectangleRed = translate (100) (0) $ color (dark red) $ rectangleSolid 60 60, 
           rectangleBlue = translate (0) (100) $ color blue $rectangleSolid 60 60, 
           rectanglYellow = translate (0) (-100) $ color yellow $rectangleSolid 60 60 
          }       
updateBoard 3.0 game = game { 
           rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60, 
           rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60, 
           rectangleBlue = translate (0) (100) $ color (dark blue) $rectangleSolid 60 60, 
           rectanglYellow = translate (0) (-100) $ color yellow $rectangleSolid 60 60 
          } 
updateBoard 4.0 game = game { 
           rectangleGreen = translate (-100) (0) $ color green $ rectangleSolid 60 60, 
           rectangleRed = translate (100) (0) $ color red $ rectangleSolid 60 60, 
           rectangleBlue = translate (0) (100) $ color blue $rectangleSolid 60 60, 
           rectanglYellow = translate (0) (-100) $ color (dark yellow) $rectangleSolid 60 60 
          } 
updateBoard _ game = game 

main :: IO() 
main = animate window background frame 
    where 
    frame :: Float -> Picture 
    frame seconds = render $ updateBoard seconds initialState 
+1

Meine Vermutung ist, dass die Muster Übereinstimmungen auf '1.0',' 2.0', etc. sind fehlgeschlagen und Sie sind auf der '_' Fall übereinstimmen. Vielleicht machen Sie vorübergehend den _ _ Fall genauso wie den '4.0' Fall und sehen Sie, ob sich das anders verhält. Kennst du die Tücken beim Vergleich von Fließkommazahlen? –

+0

[Was jeder Informatiker über Fließkomma-Arithmetik wissen sollte] (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). (Aber das Problem mit Ihrem Code ist eigentlich grundlegender als die typischen Float-Probleme.) – leftaroundabout

+0

Eine andere Sache: Bitte schreiben Sie keinen solchen repetitiven Code wie in 'updateBoard'. – leftaroundabout

Antwort

4

Nie Gleichheits-Prüfung auf Fließkommazahlen. (Oder, wenn Sie das tun, übernimmt immer das Ergebnis False sein kann, selbst wenn die Zahlen vom Konzept her gleich sind.)

In Ihrem Fall, das ist nicht einmal begrifflich der Fall, weil animate auf einigen endlichen Zeitpunkt genannt wird; warum würden diese genau eine ganzzahlige Anzahl von Sekunden umfassen?

Eine einfache Möglichkeit, um dies zu umgehen, ist die Rund-zu-ganzen-Sekunden Zeit nachschlagen.

updateBoard :: Int -> SimonGame -> SimonGame 
updateBoard 1 game = game { ... } 
updateBoard 2 game = game { ... } 
... 

main = animate window background frame 
    where 
    frame :: Float -> Picture 
    frame seconds = render $ updateBoard (floor seconds) initialState 
+0

Schutzvorrichtungen können auch zu einer akzeptablen Lösung führen. 'updateBoard t Spiel | t <1 = ...; | t <2 = ...; | t <3 = ...; | t <= 4 ...; | sonst = ... '. –

Verwandte Themen